2011-12-08 65 views
0

當我運行以下C代碼時,根據代碼是否在優化開啓(gcc -O)的情況下運行,我得到不同的輸出。使用和不使用優化訪問超出界限索引

#include <stdio.h> 

int main() 
{ 
    int b = 55; 
    int a[2] = {4, 5}; 
    int index; 

    printf(" index a[index]\n "); 
    printf("==================\n "); 

    for(index = 0; index < 6; index++) 
    { 
     printf("%2d%12d\n", index, a[index]); 
    } 

    return 0; 
} 

我明白,訪問索引外的邊界用C將簡單地從陣列訪問的堆棧存儲器進一步向下(假設分配給該指數足夠的堆棧空間,否則出現segfaults),因爲陣列是隻是C中的指針。但是優化如何影響呢?

+0

你設爲b通過讀取越界來讀取堆棧。在正常構建中,您會看到55個打印(值爲b),但是在優化構建中,b會被刪除,因此您不會看到它。 – hackworks

回答

2

訪問超出範圍是未定義的行爲。所以編譯器可以做任何事情,任何事情都可以發生。因此,試圖「猜測」會發生什麼並沒有什麼意義。

就你而言,優化可能會影響到數組之外的堆棧的排序和內容。這會給你不同的結果。

0

您正在導致未定義的行爲,很簡單。你無法真正地說「在這種情況下,爲什麼這種未定義的行爲會產生這種結果,但是在另一種情況下會產生不同的結果?」

使用objdump的GDB如果你想看到什麼指令導致堆得下優化不同

編輯:例如,與-O標誌編譯時,有第一printf(編譯爲32位的清晰度)之前單獨堆了不少的差異在main開頭:

未優化:

0x080483c4 <+0>: push ebp 
0x080483c5 <+1>: mov ebp,esp 
0x080483c7 <+3>: and esp,0xfffffff0 
0x080483ca <+6>: sub esp,0x20 
0x080483cd <+9>: mov DWORD PTR [esp+0x18],0x37 
0x080483d5 <+17>: mov DWORD PTR [esp+0x10],0x4 
0x080483dd <+25>: mov DWORD PTR [esp+0x14],0x5 
0x080483e5 <+33>: mov eax,0x8048514 
0x080483ea <+38>: mov DWORD PTR [esp],eax 
0x080483ed <+41>: call 0x80482e0 <[email protected]> 

優化:

0x080483c4 <+0>: push ebp 
0x080483c5 <+1>: mov ebp,esp 
0x080483c7 <+3>: push ebx 
0x080483c8 <+4>: and esp,0xfffffff0 
0x080483cb <+7>: sub esp,0x20 
0x080483ce <+10>: mov DWORD PTR [esp+0x18],0x4 
0x080483d6 <+18>: mov DWORD PTR [esp+0x1c],0x5 
0x080483de <+26>: mov DWORD PTR [esp],0x8048504 
0x080483e5 <+33>: call 0x80482e0 <[email protected]>