2012-04-11 198 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