栈内存有限制吗?

12

我正在浏览一个帖子。

程序崩溃了,因为它在一个函数内部声明了一个大小为10^6的数组。

给出的原因是栈上的内存分配失败导致崩溃。

当同一数组全局声明时,它可以正常工作。(存储于堆上的内存解决了问题)。

现在假设一下,栈向下增长,堆向上增长:

---栈---

-------------------

---堆----

那么,我相信如果在栈上分配内存失败, 在堆上也必定会失败。

所以我的问题是:栈大小有限制吗? (超过限制会导致程序崩溃)。 还是我漏掉了什么?


1
这里涉及到一些误解。你可能想要查看这个答案。链接 - RBT
6个回答

8

是的,栈总是有限制的。在多种语言/编译器中,您可以设置所需的大小。

通常情况下,默认值(如果没有手动设置)约为1MB对于当前的语言,这足以满足要求,除非您做一些通常不建议的事情(例如在堆栈上分配大型数组)。


6
与目前所有答案相反,在使用GCC的Linux上(我猜对于所有现代POSIX操作系统来说也是如此),最大堆栈大小是由操作系统强制执行的安全限制,可以很容易地解除。
我编写了一个小程序,递归调用一个函数,直到在堆栈上分配至少10 GB,等待终端输入,然后安全地从所有递归调用中返回到main
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <sys/resource.h>

void grow(unsigned cur_size)
{
    if(cur_size * sizeof(int) < 10ul*1024ul*1024ul*1024ul) {
        unsigned v[1000];
        v[0] = cur_size;
        for(unsigned i = 1; i < 1000; ++i) {
            v[i] = v[i-1] + 1;
        }

        grow(cur_size + 1000);

        for(unsigned i = 0; i < 1000; ++i) {
            if(v[i] != cur_size + i)
                puts("Error!");
        }
    } else {
        putchar('#');
        getchar();
    }
}

int main()
{
    struct rlimit l;
    l.rlim_max = RLIM_INFINITY;
    l.rlim_cur = RLIM_INFINITY;
    setrlimit(RLIMIT_STACK, &l);

    grow(0);
    putchar('#');
    getchar();
}

5

这完全取决于你所使用的语言和编译器。但是,例如使用 C 或 C++ 编译的程序在启动时会分配固定大小的堆栈。堆栈的大小通常可以在编译时指定(在我的特定编译器上,默认为 1 MB)。


1
我正在使用C/C++语言,编译器是gcc。操作系统平台是Windows。同时,在Linux平台上执行同样的程序时,没有运行时错误。我可以轻松地在本地声明一个大小为10^6的数组。那么,关于平台方面有什么需要注意的吗? - Vikas
1
我想在Linux上使用gcc创建一个大小为[400][3000]的浮点型二维数组,但由于内存不足而无法创建!有什么建议吗? - dom

2

您没有提到使用的编程语言,但在Delphi中,编译选项包括最大和最小堆栈大小,我相信所有编译语言都存在类似的参数。

我自己有时候必须增加最大堆栈大小。


这是C/C++编程语言。编译器是GCC。平台为Windows。请注意,如果您需要更多的帮助或者有任何其他问题,请随时提问。 - Vikas
2
@Vikas:尽量不要用“下面”来引用。SO上的帖子顺序并不是静态的。 - Xavier Ho

1

是的,大多数编程语言都有堆栈大小限制。例如,在C/C++中,如果您编写了一个不正确的递归函数(例如,错误的基本情况),则会导致堆栈溢出。这是因为,忽略尾递归,每次调用函数都会创建一个新的堆栈帧,占用堆栈空间。如果这样做足够多次,您将耗尽空间。

在Windows(VS2008)上运行此C程序...

void main()
{
    main();
}

...导致堆栈溢出:

在 Stack.exe 中未处理的异常 0x004113a9:0xC00000FD:堆栈溢出。


是的,肯定会出现运行时错误。 但我有疑问:如果数组声明在本地(堆栈上)引起了运行时错误, 为什么它在全局范围内逃脱了呢? 这意味着我们的堆大小限制大于堆栈大小。可能是默认设置! - Vikas
2
我遇到的第一个错误是“返回类型不是_int_”,因此最好先摆脱非标准代码。 - Haseeb Mir

1

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