2011-02-23 110 views
4

您好我有由海灣合作委員會(或g ++)對可能的堆棧優化問題..在FreeBSD下GCC堆棧優化

示例代碼(做UNIX方差事嗎?):

void main() { 
    char bing[100]; 
    .. 
    string buffer = ....; 
    .. 
} 

我發現了什麼在gdb中該程序的核心轉儲是bing的地址 實際上低於該緩衝區(即,& bing [0] < &緩衝區)。

我認爲這完全是在教科書中被告知的相反。有沒有 是一些編譯器優化,重新組織這種 方式的堆棧佈局?

這似乎是唯一可能的解釋,但我不知道..

如果你有興趣,信息轉儲是由於緩衝區溢出通過 兵緩衝(但也印證&兵[0] < &緩衝區)。

謝謝!

+0

刪除c標籤,因爲代碼不是c。 – 2011-02-23 01:44:04

+1

@Stephen,你怎麼知道在'main'之前沒有'typedef char * string'? :-) – paxdiablo 2011-02-23 08:36:50

回答

9

編譯器可以自由組織堆棧幀(假設它們即使是使用堆棧)也可以任意組織。

他們可能爲了對齊的原因,或出於性能的原因,或者完全沒有理由。假設任何特定的順序是不明智的。

如果您沒有通過溢出緩衝區來調用未定義的行爲,那麼您可能永遠都不會知道,而這就是它應該的方式。

編譯器不僅可以重新組織您的變量,還可以優化它們,如果它可以建立它們不被使用。隨着代碼:

#include <stdio.h> 
int main (void) { 
    char bing[71]; 
    int x = 7; 
    bing[0] = 11; 
    return 0; 
} 

比較正常的彙編輸出:

main: 
    pushl %ebp 
    movl %esp, %ebp 
    andl $-16, %esp 
    subl $80, %esp 
    movl %gs:20, %eax 
    movl %eax, 76(%esp) 
    xorl %eax, %eax 
    movl $7, (%esp) 
    movb $11, 5(%esp) 
    movl $0, %eax 
    movl 76(%esp), %edx 
    xorl %gs:20, %edx 
    je  .L3 
    call __stack_chk_fail 
.L3: 
    leave 
    ret 

與瘋狂優化:

main: 
    pushl %ebp 
    xorl %eax, %eax 
    movl %esp, %ebp 
    popl %ebp 
    ret 

發現任何從後者缺少什麼?是的,有堆棧操作爲bingx創建空間。他們不存在。事實上,整個代碼序列歸結爲:

  • 集返回代碼爲0。
  • 回報。
+0

感謝您的詳細輸入! – Figo 2011-02-23 01:57:49

8

編譯器可以自由地在堆棧上佈局局部變量(或者將它們保存在寄存器中或者用它們做別的事情),但它看起來合適:C和C++語言標準對這些實現細節沒有任何說明, POSIX或UNIX也不是。我懷疑你的教科書是否告訴過你,如果有的話,我會尋找一本新的教科書。

+0

感謝您的輸入! – Figo 2011-02-23 01:57:22

+0

我想我必須從一些關於緩衝區溢出的教科書中讀到它,它假定堆棧的佈局關於如何編寫代碼:) – Figo 2011-02-23 01:59:31

+0

儘管你對標準是正確的,但教科書習慣於先過分簡化,然後再糾正更高級課程中的具體細節。例如,你首先學習牛頓物理,然後他們告訴你它不能接近光速。編譯器文本也不會讓我感到驚訝。 – 2011-02-23 02:04:12