2015-11-30 36 views
1

這個程序編譯得很好,但是當我爲mult(x,y)的第一個參數輸入一個負數時無法執行。它顯示消息「Segmentation fault:11」。我在Windows上試過,它工作正常。我一直在OSX上的gcc上看到「Segmentation fault:11」,但在Windows上工作

當我編譯它在X代碼錯誤訊息是:線程1:EXC_BAD_ACCESS(代碼= 2,地址= 0x7fff5f3ffffc)

爲什麼這不是在OSX(酋長)工作,但在Windows罰款?非常感謝!

#include <stdio.h> 

signed succ(signed a) 
{ 
    return a+1; 
} 

signed pre(signed b) 
{ 
    return b-1; 
} 

signed add(signed c, signed d) 
{ 

    if(d == 0) return c; 

    return succ(add(c, pre(d))); 

} 


signed sub(signed e, signed f) 
{ 
    if(f == 0) return e; 

    return pre(sub(e, pre(f))); 
} 



signed mult(signed g, signed h) 
{ 
    if(h == 0 || g == 0) return 0; 

    return add(g,mult(g,pre(h))); 
} 


int main() 
{ 


    printf("mult -2,2: %i\n", mult(-2,2)); 


    return 0; 
} 
+2

您是否嘗試過使用調試器? – immibis

回答

2

這是因爲堆棧溢出的崩潰,multadd函數遞歸調用。

儘管最好使用調試器,但在每個函數中添加printf都可以幫助觀察程序流。例如改變mult到:

signed mult(signed g, signed h) 
{ 
    printf(" mult %d %d\n", g, h); 
    if(h == 0 || g == 0) return 0; 

    return add(g,mult(g,pre(h))); 
} 

並且類似地,其它功能...的輸出是:

mult -2 2 
pre 2 
mult -2 1 
pre 1 
mult -2 0 
add -2 0 
add -2 -2 
pre -2 
add -2 -3 
pre -3 
add -2 -4 
pre -4 
add -2 -5 
pre -5 
add -2 -6 
pre -6 
add -2 -7 
pre -7 
add -2 -8 
pre -8 
add -2 -9 
pre -9 
add -2 -10 
... 

並繼續調用add與遞減,直到它崩潰第二個參數。僅當該參數溢出時(在sizeof signed爲4的情況下,即32比特的情況下超過40億次迭代後發生),條件if(d == 0)將從add變爲true

當它工作時,我能想到的唯一的事情就是編譯器正在進行優化,可能會刪除函數調用。 試圖在我的Windows的x64機器上原來的程序,從MinGW的有gcc建:當內置

  • 崩潰:gcc file.c

  • gcc -O3 file.c(這裏建成運行成功,我改變了優化級別)。

在有-O3內置的可執行文件,我跑objdump -S a.exe > a.lst,這是mult功能分解:

0000000000401550 <mult>: 
    401550: 53      push %rbx 
    401551: 48 83 ec 20    sub $0x20,%rsp 
    401555: 31 c0     xor %eax,%eax 
    401557: 85 d2     test %edx,%edx 
    401559: 89 cb     mov %ecx,%ebx 
    40155b: 75 06     jne 401563 <mult+0x13> 
    40155d: 48 83 c4 20    add $0x20,%rsp 
    401561: 5b      pop %rbx 
    401562: c3      retq 
    401563: 85 c9     test %ecx,%ecx 
    401565: 74 f6     je  40155d <mult+0xd> 
    401567: 83 fa 01    cmp $0x1,%edx 
    40156a: 75 08     jne 401574 <mult+0x24> 
    40156c: 01 d8     add %ebx,%eax 
    40156e: 48 83 c4 20    add $0x20,%rsp 
    401572: 5b      pop %rbx 
    401573: c3      retq 
    401574: 83 fa 02    cmp $0x2,%edx 
    401577: 89 c8     mov %ecx,%eax 
    401579: 74 f1     je  40156c <mult+0x1c> 
    40157b: 83 ea 03    sub $0x3,%edx 
    40157e: e8 cd ff ff ff   callq 401550 <mult> 
    401583: 85 c0     test %eax,%eax 
    401585: 74 0b     je  401592 <mult+0x42> 
    401587: 01 d8     add %ebx,%eax 
    401589: 74 0d     je  401598 <mult+0x48> 
    40158b: 01 d8     add %ebx,%eax 
    40158d: 01 d8     add %ebx,%eax 
    40158f: 90      nop 
    401590: eb dc     jmp 40156e <mult+0x1e> 
    401592: 89 d8     mov %ebx,%eax 
    401594: 01 d8     add %ebx,%eax 
    401596: eb f5     jmp 40158d <mult+0x3d> 
    401598: 89 d8     mov %ebx,%eax 
    40159a: 01 d8     add %ebx,%eax 
    40159c: eb d0     jmp 40156e <mult+0x1e> 
    40159e: 90      nop 
    40159f: 90      nop 

如可以看出,他並沒有叫任何其他功能,只有本身(callq 401550 <mult> )。所以編譯器優化/內聯所有其他調用。並通過添加printf(但僅在此功能,不會打破優化),輸出爲:

mult -2 2 
mult -2 1 
mult -2 0 
mult -2,2: -4 
+0

非常感謝,爲了更好地理解程序的功能,printf是個好主意。但是,當我使用其他編譯器(例如https://www.codechef.com/ide)時,程序爲什麼會立即正常運行? –

+1

它似乎可以在線編譯器中工作,但在函數中添加'printf'時會同樣崩潰。我認爲最可能的原因是編譯器正在進行優化,甚至可能刪除函數。這將有助於查看生成的程序集。 – nnn

0

它看起來就好像有人在優化的盲點。我認爲的代碼應該會崩潰。查看優化的代碼會很有趣。我看不出什麼會導致優化器的混淆。也許優化器不考慮可能發生的符號翻轉。所以它假設一個負數減一會永遠是一個負數,例如...

相關問題