C - 强制字符串参数在只读存储器中

问题描述 投票:1回答:1

我正在优化一些代码,我有这样的函数:

const char * gStrPtr = NULL;

void foo (const char *str) {
     gStrPtr = strdup(str);
}

截至目前,foo()仅用常量字符串调用。例如:

const char fooStr[]="Some really long string...";
foo(fooStr);

请注意,因为它始终使用常量调用,所以我应该能够:

void foo (const char *str) {
     gStrPtr=str;
}

但是,它打开了一个尖锐的棍子:如果将来有人违反惯例,并尝试使用稍后释放的字符串的动态副本调用foo(),则可能导致未定义的行为。

我想知道是否有可能创建一个编译时甚至运行时检查,检查str是否在只读内存中,以避免昂贵的bug追逐。

注意:如果我假设str是一个字符串文字,那么我可以用宏来做到这样:

#define foo(str)  foo_func("" str)

这将导致非字符串文字的编译错误。但它也不接受const chars的指针。


编辑

我想我会在下面的讨论之后发布这个。 @CraigEtsy指出使用__builtin_constant_p,这是解决这个问题的最佳方法(但可能满足我的需求)。我用这个做了以下测试,得到了这些结果:

void foo(const char *str) {
        if (__builtin_constant_p(*str))
                printf("%s is constant\n", str);
        else
                printf("%s is not constant\n", str);
}

const char globalArray[] = "globalArray";
const char *globalPtr = "globalPtr";

int main()
{
    const char localArray[]="localArray";
    const char *localPtr="localPtr";
    char localNonConst[]="localNonConst";
    foo("literal");     // constant
    foo(localArray);    // not constant
    foo(localPtr);      // constant
    foo(globalArray);   // constant
    foo(globalPtr);     // not constant
    foo(localNonConst); // not constant
}

当使用-O3编译时,它给出了结果:

literal is constant
localArray is not constant
localPtr is constant
globalArray is constant
globalPtr is not constant
localNonConst is not constant

因此,对于我的特殊情况,我可以将const char arr[]="str"切换到const char * arr="str",然后,在我的foo()中,我可以检查值是否为常量,并分配内存并提高运行时警告(如果没有)(并标记一个标志,所以我知道是否稍后释放指针...)。

c gcc
1个回答
1
投票

我认为没有任何合理的方法可以在运行时强制执行此操作,至少在没有机器的情况下,这比仅仅调用strdup要贵很多个数量级。

如果函数只被认为是将不可变的字符串作为参数(这就是你正在寻找的单词 - 不可变的,从某种意义上说,它的生命周期将是进程生命周期的剩余部分,其内容不会因为其余部分而改变生命周期),这需要是其接口合同的文档部分。

© www.soinside.com 2019 - 2024. All rights reserved.