我们有这个函数原型:
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";