如何让gcc警告返回局部变量的地址?

md5*_*md5 12 c gcc gcc-warning

gcc4.4.5中,我发出以下代码的警告.

char *f(void)
{
    char c;
    return &c;
}
Run Code Online (Sandbox Code Playgroud)

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

char *f(void)
{
    char c;
    char *p = &c;
    return p;
}
Run Code Online (Sandbox Code Playgroud)

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

Pas*_*uoq 9

编译器和大多数静态分析器不会尝试警告程序可能出错的一切,因为这会导致太多误报(警告与源代码中的实际问题不对应).

Macmade 在评论中推荐Clang,我可以推荐.请注意,Clang仍然旨在通过最大限度地减少误报来为大多数开发人员提供帮助.这意味着它有错误的否定,换句话说,它错过了一些真正的问题(当不确定存在问题时,它可能保持沉默,而不是冒着浪费开发人员时间的假阳性).


请注意,f()程序中的功能是否确实存在问题,这甚至是有争议的.h()下面的函数显然很好,虽然调用代码p返回后不能使用:

char *p;

void h(void)
{
    char c;
    p = &c;
}
Run Code Online (Sandbox Code Playgroud)

我可以推荐的另一个静态分析器是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
... 
Run Code Online (Sandbox Code Playgroud)

以上只是提供信息的消息,并不意味着功能必然是错误的.我的功能h()也有一个:

h.c:7:[value] warning: locals {c} escaping the scope of h through p
Run Code Online (Sandbox Code Playgroud)

在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>).
Run Code Online (Sandbox Code Playgroud)

Frama-C的价值分析称为上下文敏感.它分析h()每个调用的函数,以及实际传递给它的值.它还分析了h()在函数调用之后caller()带有实际可以返回的值的代码h().这比Clang或GCC通常做的上下文不敏感分析更昂贵,但更精确.