堆栈内存有限制吗?

Posted

技术标签:

【中文标题】堆栈内存有限制吗?【英文标题】:Is there any limit on stack memory? 【发布时间】:2011-02-16 07:55:18 【问题描述】:

我正在处理其中一个线程。 一个程序崩溃了,因为 它在函数中本地声明了一个 10^6 的数组。

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

当全局声明相同的数组时,它工作得很好。(堆上的内存保存了它)。

现在,让我们假设, 栈向下增长,向上堆。

我们有:

---堆栈---

-------

---堆----

现在,我相信如果堆栈分配失败, 它也必须在堆上失败。

所以我的问题是:堆栈大小有限制吗? (越界导致程序崩溃)。 还是我错过了什么?

【问题讨论】:

这里有一点神话。您可能想查看this 的答案。 【参考方案1】:

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

【讨论】:

我正在使用 C/C++。编译器是 gcc.Windows 平台。此外,我在 linux 平台上也没有运行时错误。我可以轻松地在本地声明一个大小为 10^6 的数组。那么平台呢? 我想创建一个 [400][3000] 大小的浮点二维数组 .... 在 linux 上使用 gcc 但由于内存不足无法!有什么建议吗????【参考方案2】:

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

我自己当然不得不偶尔增加最大值。

【讨论】:

它是 C/C++。编译器-GCC。平台:Windows。也请阅读下面我的 cmets。 @Vikas:尽量不要通过“下面”来引用。 SO 上的帖子顺序不是一成不变的。 @Xavier:哦,我明白了。谢谢你的信息。 :)【参考方案3】:

是的,大多数语言的堆栈大小都有限制。例如,在 C/C++ 中,如果您有一个不正确编写的递归函数(例如不正确的基本情况),您将溢出堆栈。这是因为,忽略tail recursion,每次调用函数都会创建一个新的stack frame,它会占用堆栈空间。这样做够了,你会用完空间。

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

void main()

    main();

...导致堆栈溢出:

Unhandled exception at 0x004113a9 in Stack.exe: 0xC00000FD: Stack overflow.

【讨论】:

是的,肯定会给出运行时错误。但我的疑问是:如果本地数组声明(在堆栈上)导致运行时错误。为什么它在全球范围内逃脱。意味着我们的堆大小限制大于堆栈大小。可能是默认的! 我得到的第一个错误是 返回类型不是 int 所以最好先摆脱非标准代码。【参考方案4】:

也许不是一个很好的答案,但可以让您更深入地了解 Windows 通常如何管理内存:Pushing the Limits of Windows

【讨论】:

【参考方案5】:

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

通常默认值(如果未手动设置)约为当前语言为 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();

【讨论】:

以上是关于堆栈内存有限制吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何排空java线程栈内存区?

JVM的内存结构里的那个堆和栈,和数据结构里的堆和栈是一个东西吗?

void函数中不写return语句会占用栈内存吗?

JavaScript 内存限制

在java中的堆栈内存上创建对象?

堆栈与ESP(栈指针寄存器)