如何让gcc警告返回本地变量地址的方法?

12

我使用 gcc 4.4.5 版本时,以下代码会产生警告。

char *f(void)
{
    char c;
    return &c;
}

但是,当我使用一个临时指针时,就不再有警告了(即使行为是错误的)。

char *f(void)
{
    char c;
    char *p = &c;
    return p;
}

我听说在C语言中指针分析很困难,但是gcc可以警告这样的代码吗?


Clang在这方面要好得多,而且还包括一个静态分析工具,应该能够发现这种错误。如果可以的话,你应该试一试。 - Macmade
也许最好让你的同行审查你的代码并使用编码标准? - Ed Heal
为什么返回局部变量的地址是错误的,应该返回什么?(这里是 C 语言新手) - Yahya Uddin
2个回答

9

编译器和大多数静态分析器并不尝试警告程序可能出现的所有错误,因为那将导致太多的虚警(警告在源代码中没有实际问题)。

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输出中的“assert”一词所表达的真正错误是,如果一个函数调用了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的值分析被称为上下文敏感。它针对每个调用分析函数h(),使用实际传递给它的值。它还分析在函数caller()中调用h()后面的代码,使用实际可以由h()返回的值进行分析。这比Clang或GCC通常执行的上下文无关分析更昂贵,但更精确。

1
在这个第一个例子中,gcc可以清楚地看到您正在返回一个将不再存在的自动变量的地址。在第二个例子中,编译器必须遵循您程序的逻辑,因为p可能指向一些有效的东西(例如外部字符变量)。
尽管gcc在这里不会抱怨,但它会对像这样使用指针的情况发出警告:
char *f(const char *x)
{
  char *y = x;
  ...
}

再次强调,您在此定义中删除了“const”限定符,这一点毫无疑问。

另一个可以检测到此问题的实用程序是splint(http://splint.org)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接