2011-10-28 106 views
3

這裏是我的代碼:這是一個gcc優化錯誤嗎?

bool func(const MY_STRUCT *const ptr, some_struct *x, int y) 
{ 
    printf("IN: %p\n", ptr); // ok 
    for (int i = 0; i < y; ++i) { 
     if (ptr->foo(x[i].key) == 0) { 
      return false; 
     } 
    } 
    printf("OUT: %p\n", ptr); // ok 
    return true; 
} 

void process(void) 
{ 
    ... ... 
    for (i = 0; i < num; ++i) { 
     MY_STRUCT *ptr = obj->GetPtr(); // success 
     printf("BEFORE: %p\n", ptr); // ok 
     if (func(ptr, x, y) == false) { 
      continue; 
     } 
     printf("AFTER: %p\n", ptr); // <nil> when compile with -O2 
     printf("%s", ptr->data); // *** segment fault here *** 
    } 
} 

輸出:

BEFORE: 0x0612d3fa 
IN: 0x0612d3fa 
OUT: 0x0612d3fa 
AFTER: <nil> 
segment fault 

如果我編譯上面的代碼用-O0,一切工作正常。 但是,如果我使用-O2編譯它,在函數func被調用後,ptr變爲NULL

這是一個海灣合作委員會的錯誤?有沒有人遇到類似的錯誤?

我的gcc版本是:gcc version 3.4.5 20051201 (Red Hat 3.4.5-2)

+0

你可能在'func'中的「做某事」代碼中存在一個bug,該代碼會搗毀調用者的'ptr' –

+6

也許這是一個編譯器的bug,但在開始搜索之前,在valgrind下運行你的程序,確定沒有內存訪問問題。也許你在某處存在堆棧損壞。 –

+7

這是代碼中的99.999%的錯誤。請發佈更多代碼和實際用法+執行輸出。 –

回答

1

存在(可能)您在func中存在堆棧碎片的可能性,它將覆蓋調用者堆棧上的ptr。確保func中的任何數組或結構訪問保持在邊界內。如果不是因爲我對gcc 3.x的回憶,我會說這幾乎肯定是實際發生的事情。即便如此,這是最可能的解釋。

給你在這一點上,疑點利益,如果你的代碼是真的,張貼在你的問題,那麼,這可能是一個編譯器錯誤:

printf("BEFORE: %p\n", ptr); // ok 
    if (func(ptr, x, y)) { 
     continue; 
    } 
    printf("AFTER: %p\n", ptr); // <nil> when compile with -O2 

ptr是按值傳遞到func,所以它的調用函數的值不應該改變,不管在func內發生了什麼。

但是,您使用的是真正古老的編譯器;即使你報告這個錯誤,也不會有任何結果。這很可能是因爲gcc已經改變了很久以前。嘗試更新的版本或不同的編譯器。

+0

謝謝。我將嘗試稍後使用gcc4編譯它併發布結果。奇怪的是'ptr'總是'NULL'。我認爲如果'func'中的某個東西重寫'ptr'的值,它將是一個隨機值,幾乎不可能是0。 – iCoder

1

無論錯誤編譯器可能會或可能不會有,如果你看到你發佈的代碼所描述的問題,那麼你的GCC在任何優化級別打破。

根本不應該達到有問題的代碼行。

func總是返回true,如果返回true,則會跳過循環體的最後一部分。

如果您懷疑有編譯器錯誤,請先編寫一個代碼樣本來重現它。

當我們不知道你的實際代碼是什麼樣的,我們不可能猜測GCC的行爲是否正確。

+0

我假設在'//做些事情'的某個地方有'return false';另一種選擇簡直太可怕了。 –

+0

很有可能,但是如果我們不知道它在哪裏,還有什麼可能發生,那麼就不可能猜測正確的行爲應該是什麼 – jalf

+0

哦,絕對。 –