确保函数参数的静态存储

我们有这个函数原型:

  BNode *b_new_node(const char *name, int pos, int len, const char *val);

大多数使用此代码(和类似代码)的代码都是自动生成的代码,如下所示:

 b = b_new_node("foo.bar.id.1", 0, 10, some_data);

该函数分配一个新的BNode并将val字符串复制到其中,但它只是将名称成员分配给指针,例如

 b_strlcpy(new_node->val, val, sizeof new_node->val);
 new_node->name = name;

如果b_new_node中的第一个参数(“foo.bar.id.1”,0,10,some_data),则会破坏这种破坏;不是字符串文字,或者是具有静态存储持续时间的东西,但是例如堆栈上的缓冲区.

无论如何,使用gcc(其他编译器也很感兴趣),我们可以通过编译时间检查传入此参数是静态存储吗?

(当然,避免这些可能问题的简单方法是将该参数复制到节点中 – 我们使用该方法进行的测量将内存需求提高50%并使程序减慢10%,因此该方法是不合需要的).

最佳答案 这将检测字符串文字:

#include <stdio.h>

#define PRINT_IT(c) do {\
if (__builtin_constant_p(c))\
    print_it(c, 1);\
else \
    1/__builtin_constant_p(c);\
} while (0)


void print_it(const char *c, int is_static)
{
    printf("%s is a constant %d\n", c, is_static);
}

int main(int argc, char *argv[])
{
    char bar[] = "bar";
    PRINT_IT("Foo"); //line 19
    PRINT_IT(bar);   //line 20

return 0;

}


$gcc  foo.c 
foo.c: In function ‘main’:
foo.c:20: warning: division by zero

因此,您可以将b_new_node()函数包装在宏中,可能仅用于调试版本,并利用除零警告.

请注意,它仅将字符串文字检测为“参数”,而不是静态存储,例如

const char *foo = "foo";
PRINT_IT(foo); //will generate a warning
PRINT_IT("foo"); //will not generate a warning
PRINT_IT(global_foo); //will generate a warning, even when. 
                      //global_foo is const char *foo = "foo"; or
                      //global_foo is const char foo[] = "foo";
点赞