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

时间:2018-09-13 18:37:13

标签: c gcc

我正在优化一些代码,并且具有如下功能:

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是否在只读内存中,以避免日后昂贵的错误追赶。

注意:如果我假设str是字符串文字,那么可以使用宏来实现它:

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

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


编辑

我认为我将在下面的讨论之后发布此内容。 @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()中,我可以检查该值是否恒定,并且分配内存,如果没有,则发出运行时警告(并标记一个标志,以便以后知道是否释放指针...)。

1 个答案:

答案 0 :(得分:1)

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

如果该函数仅应将 immutable 字符串用作参数(这就是您要查找的词-不可变,就某种意义而言,该函数的生存期将是该进程生存期的剩余部分,它的内容在其整个生命周期的剩余时间内都不会改变),这需要成为其接口合同中记录在案的一部分。