对于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
真正的错误,以 Frama-C 输出中的“断言”一词为特征,是函数调用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>).
Frama-C 的价值分析称为context-sensitive。它分析h()
每个调用的函数,以及实际传递给它的值。它还使用实际可以返回的值分析调用h()
in 函数之后的代码。这比 Clang 或 GCC 通常执行的上下文不敏感分析更昂贵,但更精确。caller()
h()
在第一个示例中,gcc 可以清楚地看到您正在返回一个不再存在的自动变量的地址。其次,编译器必须遵循程序的逻辑,因为 p 很容易指向有效的东西(例如,外部字符变量)。
虽然 gcc 不会在这里抱怨,但它会警告指针使用,如下所示:
char *f(const char *x)
{
char *y = x;
...
}
同样,它可以毫无疑问地看到您正在删除此定义中的 'const' 限定符。
将检测此问题的另一个实用程序是夹板(http://splint.org)。