簡體   English   中英

如何使gcc警告有關返回局部變量的地址?

[英]How to make gcc warn about returning the address of local variables?

使用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的輸出中以單詞“ 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通常進行的上下文無關的分析更為昂貴,但更為精確。

在第一個示例中,gcc可以清楚地看到您正在返回一個不再存在的自動變量的地址。 第二,編譯器必須遵循程序的邏輯,因為p可以輕松指向有效的內容(例如,外部字符變量)。

盡管gcc在這里不會抱怨,但它會警告使用指針,如下所示:

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

同樣,它可以毫無疑問地看到您正在刪除此定義中的“ const”限定詞。

可以檢測到此問題的另一個實用程序是splint(http://splint.org)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM