2012-04-11 116 views
5

導致堆棧溢出的一個顯而易見的方式是獲得Segmentation fault,將遞歸地將堆棧幀疊加到彼此的頂部,直到它繁榮。我想知道如果堆棧溢出可能發生,甚至沒有推動新的堆棧幀。如何溢出堆棧而不推送新的堆棧幀?

創建一個足夠大的陣列也可以從經驗中做到,但是還有其他可能的場景嗎?

+0

這將在Linux/UNIX環境中。 – 2012-04-11 09:08:09

+1

'alloca'和VLA。 – Mat 2012-04-11 09:09:07

回答

3

C99使用可調整大小的數組,您可以使用它並將其調整爲較大的數組。然而,這個可調整大小的陣列使用alloca來實現。下面是UNIX ENV一個示例代碼:

#include <stdio.h> 
#include <alloca.h> 
#include <stdlib.h> 
#include <stdbool.h> 

int 
main() 
{ 
    while (true) 
    { 
     void *p = alloca(32UL); 
     printf("new memory allocated at %p \n", p); 
    } 
    exit(EXIT_SUCCESS); 
} 

而且你的輸出看起來就像這樣

new memory allocated at 0xbf800a60 
new memory allocated at 0xbf800a30 
new memory allocated at 0xbf800a00 
new memory allocated at 0xbf8009d0 
new memory allocated at 0xbf8009a0 
[1] 3977 segmentation fault ./a.out 

alloca是在malloc家庭的功能,但它通過調整棧上分配的內存堆棧指針。

1

濫用alloca()_alloca()如果你正在開發的Windows SDK/VS:

的ALLOCA()函數分配的空間大小字節在 調用者的堆棧幀。

注意_alloca()現在被棄用,有利於_malloca()

1

從根本上說,「堆棧」只是一些內存,當ESP/EBP超出這個內存的界限時,堆棧溢出。

  1. 創造了巨大的堆棧分配的陣列,它比其餘的堆棧空間的尺寸更大:int x[10000000];
  2. ESP直接設置:__asm mov esp, 0x0
  3. 您可以通過多種方式實現這一點破壞堆棧,因此噹噹前函數展開時,ESP/EBP將被設置爲垃圾:int x; memset(&x, 0, 10000000);

And coun tless其他方式...

1

通過聲明和使用數組比你的堆棧大小:

$ ulimit -s 
8192 
$ 

然後

int main(void) 
{ 
    volatile char bla[8192 * 1024 + 16] = {0}; 
} 

很可能在執行時出現段錯誤。

+0

爲什麼輸入volatile?在我的示例中爲 – 2012-04-11 09:30:22

+0

,以避免編譯器優化它,因爲它不在程序中的其他地方使用。如果你使用'printf'打印'for'循環來打印所有元素,那麼你不需要'volatile'限定符,因爲編譯器無法優化它。 – ouah 2012-04-11 09:32:17