如何在不推入新的栈帧的情况下溢出堆栈?

5

显然,导致堆栈溢出并获得 Segmentation fault 的一种明显方法是递归地将堆栈帧推到彼此之上,直到崩溃。我想知道是否可以在不压入新的堆栈帧的情况下发生堆栈溢出。

从经验上讲,创建足够大的数组也可能导致堆栈溢出,但还有其他可能的情况吗?


这将在Linux/UNIX环境中进行。 - Ann Brown
4个回答

3

C99使用可调整大小的数组,您可以使用并不断调整它到更大的数组。然而,这个可调整大小的数组是使用alloca实现的。下面是在UNIX环境中的示例代码:

#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
通过声明和使用一个比你的堆栈大小更大的数组:
$ ulimit -s
8192
$

那么

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

执行时很可能发生段错误。


在我的例子中,为了避免编译器将其优化掉,因为它在程序的其他地方没有被使用,我使用了volatile关键字。如果您使用printf打印所有元素的for循环,则不需要volatile限定符,因为编译器无法将其优化掉。 - ouah

1

如果您正在使用Windows SDK / VS进行开发,请滥用alloca()_alloca()

alloca()函数在调用者的堆栈帧中分配大小为size字节的空间。

请注意,_alloca()现已弃用,推荐使用_malloca()


1

从根本上讲,“堆栈”只是一些内存,当ESP / EBP超出此内存的边界时,就会发生堆栈溢出。

您可以通过多种方式实现此目标:

  1. 创建一个巨大的堆栈分配数组,其大小大于剩余堆栈空间的大小:int x[10000000];
  2. 直接设置ESP:__asm mov esp, 0x0
  3. 破坏堆栈,以便在当前函数展开时,ESP / EBP将被设置为垃圾:int x; memset(&x, 0, 10000000);

还有无数其他方法...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接