簡體   English   中英

為什么僅在使用 gcc 編譯器優化時,當我錯誤地返回指向堆棧上的值的指針時,printf 打印 0?

[英]Why does printf print 0s when I wrongly returned pointer to value on the stack only when optimizing with gcc compiler?

我試圖了解此示例中 printf 的行為。 當然,這里的主要問題是我們正在返回一個指向堆棧上的值的指針,該值在 function Boo 返回后彈出。

我用 gcc 編譯。 在 test1 中:我得到了 7 打印兩次,這是預期的。 以及 test2 中第二個 printf 上的垃圾值。 但是當我用 gcc -O3 編譯時,我在兩種情況下都打印了 0並且編譯器警告關於返回局部變量的地址。

test.c: In function 'Foo': test.c:8:12: warning: function returns address of local variable [-Wreturn-local-addr] return t; ^ test.c:5:9: 注意:此處聲明為 int j;

有人可以幫我解釋導致這種行為的 printf 的行為如何嗎?

int *Boo(int i, int *p)
{
    int j;
    int *t = &j;
    *t = i + *p;
    return t;
}

void Foo(int x)
{
    if (x == 0) { return;}
    Foo(x - 1);
}

//test1
int main(void)
{
    int x = 5;
    int *t = Boo(2, &x);
    printf("%d", *t);
    printf("%d", *t);

    return 0;
}

//test2
int main(void)
{
    int x = 5;
    int *t = Boo(2, &x);
    
    printf("%d", *t);
    Foo(8);
    printf("%d", *t);

    return 0;
}

GCC 看到Boo返回一個指向局部變量的指針,因此任何使用該指針的嘗試都是未定義的行為。 這意味着,根據 C 標准,編譯器可以為所欲為,在這種情況下,GCC 通常會生成“高效”的代碼,即使它與程序員的意圖完全無關。 它內聯了對Boo的調用,它沒有可見的效果,因此被優化掉了,它選擇了一種“有效”的方式來為printf提供一個參數,它恰好是常數 0。

參見神螺栓 printf 的printf參數進入esi ,它來自ebp ,它被歸零。 我想有一個錯過的優化,因為它在調用printf以重新加載到esi時將相同的 0 保存在ebp中,而不是之后重新歸零esi 但整個分析有點毫無意義,因為行為是未定義的。

Boo本身被優化為 function ,它只返回一個NULL指針並且不執行任何其他操作,由於未定義的行為,這再次是合法的,但該版本的Boo不被程序調用。 Foo也被優化為 function 立即返回而不遞歸; 編譯器可以判斷遞歸調用無效。 (如果將否定參數傳遞給Foo ,由於簽名的 integer 溢出,您將有未定義的行為,因此編譯器不需要處理這種情況。)

暫無
暫無

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

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