C/C++程序的最大堆栈大小是多少?

23

我已经尝试过下面的程序。创建该程序的意图是为了更多地了解堆栈大小。

int main()
{
    int nStack[100000000];
    return 0;
}

执行上述代码后,程序由于分配了巨大的堆栈空间而崩溃。 堆栈的最大可能大小是多少?它对每个程序/计算机来说是固定的吗?它可以增加吗?

出于知识的缘由,我想知道。如果有人能提供C/C++代码示例,那将非常有帮助。


你尝试过使用这个吗?getrlimit/setrlimit - Saurabh Meshram
移除[java]标签,因为这个问题似乎与Java无关。 - Peter Lawrey
1
Pthreads允许您为新线程提供自己的堆栈。您可以动态分配大量内存,然后使用该内存作为其堆栈启动线程。 - Kerrek SB
在许多嵌入式处理器上,堆栈大小为十六个字。 - Pete Becker
@PeteBecker 只适用于低空闲优先级的“LED闪烁”线程。 - Martin James
6个回答

20

栈的最大大小是多少?

取决于实现方式。现在在PC上,一到几兆字节是典型的大小。

对于每个程序/计算机,它是固定的吗?

通常固定在链接时,但标准并未定义如此。某些操作系统也可以在运行时限制堆栈(例如linux上的RLIMIT_STACK)。

它可以增加吗?

这可能取决于实现方式。请查看您的链接器文档以获取详细信息。还需要查看操作系统和可执行格式的文档。

您应该将大型数组动态分配。


在这种情况下,我们如何知道我们的程序会消耗多少堆栈??? - pkthapa
一般来说,这是不可能的。对于不使用递归或可变长度数组的程序,通常可以假设堆栈不会增长太大。 - fuz
实际上,这通常是由链接器而不是编译器来修复的。 - Martin James
@MartinJames 谢谢您指出这一点,我已经纠正了这个细节。 - eerorika
像C#这样的托管语言是否也有堆栈内存的限制?我的意思是,堆栈内存总是有限的,但对于它们来说是否太小了?我只是想知道CLR如何分配一个大型数组,该数组仅局限于函数?这样的数组肯定只会进入堆栈内存区域。 - RBT
1
@RBT 是的,CLR 也适用于堆栈限制。我不太了解 C#,但是通过一些搜索可以发现,在 C# 中,除非使用 stackalloc 关键字,否则所有数组变量都分配在堆上(即动态分配)。 - eerorika

9

对于基于Linux的应用程序,我们可以使用getrlimit和setrlimit API来了解各种内核资源限制,例如core文件大小、CPU时间、堆栈大小、nice值、最大进程数等等。'RLIMIT_STACK'是在Linux内核中定义的堆栈的资源名称。下面是一个简单的程序来检索堆栈大小:

#include <iostream>
#include <sys/time.h>
#include <sys/resource.h>
#include <errno.h>
using namespace std;

int main()
{
   struct rlimit sl;
   int returnVal = getrlimit(RLIMIT_STACK, &sl);
   if (returnVal == -1)
   {
      cout << "Error. errno: " << errno << endl;
   }
   else if (returnVal == 0)
   {
      cout << "stackLimit soft - max : " << sl.rlim_cur << " - " << sl.rlim_max << endl;
   }
}

0

我尝试了下面的程序。

int main()
{
    int nStack[519492];
    cout<<"Okay!";
    return 0;
}

输出:
Okay!

但是如果我将数组大小增加1个字节,程序就会崩溃。

int main()
{
    int nStack[519493];
    cout<<"Okay!";
    return 0;
}

输出:

No output. Program crashes.

0

对于这种类型,您可以为此分配动态内存分配,并使用通用堆栈表示进行内存分配。如果需要大量的内存,可以使用链表作为堆栈的形式。对于C/C++,可以使用Malloc/New进行动态内存分配。希望您能理解。


0
在虚拟内存的出现之前,比如在V7 Unix中,我认为堆栈没有固定的限制。堆栈自顶向下增长,而堆从底部(好吧,从文本+数据空间的顶部)向上增长。只要它们没有相遇(“不要让横梁交叉!”),就可以正常运行。
有一个限制是堆栈每次增长的限制。如果你有一个分配了1K本地变量的函数,你可以递归调用它几十次,直到出问题。但如果你有一个分配了10K本地变量的函数,它倾向于立即崩溃。
发生的情况是操作系统注意到你的堆栈访问是否超过了已经为堆栈分配的边界。如果你稍微超出堆栈的末端,操作系统会假设堆栈正在增长,并为你分配更多的空间。但如果你试图一次性大幅增加堆栈大小,实际上得到的是类似于偏离指针引用的东西,位于堆栈顶部和堆的顶部之间,并且导致段错误。

(这是我从记忆中得知的,所以细节可能有误。如果我再次启动旧的PDP-11,我将要记得测试一下。)


-1

要更改由进程加载器引发的主线程分配的堆栈大小以运行其入口点处的代码,请查看链接器文档。还可以在可执行文件头元数据中编辑该堆栈大小。


1
如果您能与我们分享如何像您上面所说的那样编辑堆栈大小,那将非常有帮助和信息性。我对此一无所知。 - pkthapa

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