堆栈内存有限制吗?
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();
【讨论】:
以上是关于堆栈内存有限制吗?的主要内容,如果未能解决你的问题,请参考以下文章