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

时间:2012-09-01 14:50:04

标签: c gcc gcc-warning

使用gcc 4.4.5,我收到以下代码的警告。

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

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

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

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

2 个答案:

答案 0 :(得分:9)

编译器和大多数静态分析器不会尝试警告程序可能发生的所有错误,因为这会产生太多的误报(警告与源代码中的实际问题不对应)。

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


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

char *p;

void h(void)
{
    char c;
    p = &c;
}

我可以推荐的另一个静态分析器是Frama-C's value analysis(我是其中一个开发人员)。对于某些错误系列(包括悬空指针),当在受控条件下使用时,这一点不会留下任何误报。

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

答案 1 :(得分:1)

在第一个例子中,gcc可以清楚地看到你正在返回一个不再存在的自动变量的地址。在第二种情况下,编译器必须遵循程序的逻辑,因为p可以很容易地指向有效的东西(例如外部字符变量)。

虽然gcc不会在这里抱怨,但它会用这样的指针使用警告:

char *f(const char *x)
{
  char *y = x;
  ...
}

同样,毫无疑问,您可以在此定义中删除'const'限定符。

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