我使用 gcc
4.4.5 版本时,以下代码会产生警告。
char *f(void)
{
char c;
return &c;
}
但是,当我使用一个临时指针时,就不再有警告了(即使行为是错误的)。
char *f(void)
{
char c;
char *p = &c;
return p;
}
我听说在C语言中指针分析很困难,但是gcc
可以警告这样的代码吗?
我使用 gcc
4.4.5 版本时,以下代码会产生警告。
char *f(void)
{
char c;
return &c;
}
但是,当我使用一个临时指针时,就不再有警告了(即使行为是错误的)。
char *f(void)
{
char c;
char *p = &c;
return p;
}
我听说在C语言中指针分析很困难,但是gcc
可以警告这样的代码吗?
编译器和大多数静态分析器并不尝试警告程序可能出现的所有错误,因为那将导致太多的虚警(警告在源代码中没有实际问题)。
Macmade在评论中推荐Clang,我也可以赞同这个建议。请注意,Clang仍旧致力于通过最小化虚警来对大多数开发者有用。这意味着它会漏报一些真实问题(当不确定是否存在问题时,它可能保持沉默而不冒险浪费开发者的时间进行虚警)。
f()
是否真的存在问题是有争议的。下面的函数h()
显然没有问题,尽管调用代码在其返回后不应使用p
。char *p;
void h(void)
{
char c;
p = &c;
}
我可以推荐另一个静态分析器Frama-C的值分析(我是其中一位开发人员)。在受控条件下使用时,对于某些错误家族(包括悬挂指针),它不会留下任何假阴性。
char *f(void)
{
char c;
return &c;
}
char *g(void)
{
char c;
char *p = &c;
return p;
}
$ frama-c -val -lib-entry -main g r.c
...
r.c:11:[value] warning: locals {c} escaping the scope of g through \result
...
$ frama-c -val -lib-entry -main f r.c
...
r.c:4:[value] warning: locals {c} escaping the scope of f through \result
...
h()
也有一个提示:h.c:7:[value] warning: locals {c} escaping the scope of h through p
h()
然后使用了p
。void caller(void)
{
char d;
h();
d = *p;
}
$ frama-c -val -lib-entry -main caller h.c
...
h.c:7:[value] warning: locals {c} escaping the scope of h through p
...
h.c:13:[kernel] warning: accessing left-value p that contains escaping addresses; assert(Ook)
h.c:13:[kernel] warning: completely undefined value in {{ p -> {0} }} (size:<32>).
h()
,使用实际传递给它的值。它还分析在函数caller()
中调用h()
后面的代码,使用实际可以由h()
返回的值进行分析。这比Clang或GCC通常执行的上下文无关分析更昂贵,但更精确。char *f(const char *x)
{
char *y = x;
...
}
再次强调,您在此定义中删除了“const”限定符,这一点毫无疑问。
另一个可以检测到此问题的实用程序是splint(http://splint.org)。