【问题标题】:How to make gcc warn about returning the address of local variables?如何使 gcc 警告返回局部变量的地址?
【发布时间】:2012-09-01 14:50:04
【问题描述】:

对于gcc 4.4.5,我收到以下代码的警告。

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

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

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

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

【问题讨论】:

  • Clang 在这方面要好很多,并且还包括一个静态分析工具,应该可以看到这种错误。如果可以的话,你应该试一试。
  • 也许最好让你们中的一位同行来审查您的代码并使用编码标准?
  • 为什么返回局部变量的地址是错误的,应该是什么? (这里是C新手)

标签: c gcc gcc-warning


【解决方案1】:

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

Macmade 在 cmets 中推荐 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(),以及实际传递给它的值。它还分析了在函数caller() 中调用h() 之后的代码以及h() 实际可以返回的值。这比 Clang 或 GCC 通常执行的上下文不敏感分析更昂贵,但更精确。

【讨论】:

    【解决方案2】:

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

    虽然 gcc 不会在这里报错,但它会像这样使用指针发出警告:

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

    同样,它可以毫无疑问地看到您正在删除此定义中的 'const' 限定符。

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

    【讨论】:

      猜你喜欢
      • 2011-10-17
      • 2013-01-30
      • 2019-06-15
      • 2011-04-13
      • 1970-01-01
      • 2015-04-25
      • 2016-08-15
      • 2023-03-11
      相关资源
      最近更新 更多