有关堆栈分配的许多相关问题可以理解
What and where are the stack and heap?
Why is there a limit on the stack size?
但是在各种* nix机器上我可以发出bash命令
ulimit -s unlimited
或csh命令
set stacksize unlimited
这如何改变程序的执行方式?对程序或系统性能有任何影响(例如,为什么这不是默认值)?
如果有更多系统细节相关,我最关心的是在x86_64硬件上运行的Linux上使用GCC编译的程序。
答案 0 :(得分:23)
调用函数时,会在堆栈上分配新的“命名空间”。这就是函数可以有局部变量的方式。随着函数调用函数,函数又调用函数,我们不断在堆栈上分配越来越多的空间来维护命名空间的深层次结构。
要使用大量堆栈空间来限制程序,通常会通过ulimit -s
实施限制。如果我们通过ulimit -s unlimited
删除该限制,我们的程序将能够为其不断增长的堆栈继续吞噬RAM,直到最终系统完全耗尽内存。
int eat_stack_space(void) { return eat_stack_space(); }
// If we compile this with no optimization and run it, our computer could crash.
通常,使用大量的堆栈空间是偶然的,或者是非常深的递归的症状,可能不应该如此依赖堆栈。因此堆栈限制。
对绩效的影响很小但确实存在。使用time
命令,我发现消除堆栈限制会使性能提高几分之一秒(至少在64位Ubuntu上)。
答案 1 :(得分:2)
Mea culpa,堆栈大小可以确实无限制。 _STK_LIM
是默认,_STK_LIM_MAX
是每个架构不同的东西,从include/asm-generic/resource.h
可以看出:
/*
* RLIMIT_STACK default maximum - some architectures override it:
*/
#ifndef _STK_LIM_MAX
# define _STK_LIM_MAX RLIM_INFINITY
#endif
从这个例子中可以看出,通用值是无限的,其中RLIM_INFINITY
在一般情况下定义为:
/*
* SuS says limits have to be unsigned.
* Which makes a ton more sense anyway.
*
* Some architectures override this (for compatibility reasons):
*/
#ifndef RLIM_INFINITY
# define RLIM_INFINITY (~0UL)
#endif
所以我猜真正的答案是 - 堆栈大小可以受到某些架构的限制,然后无限堆栈跟踪将意味着定义的任何_STK_LIM_MAX
,并且如果它是无限的 - 它是无限的。有关将其设置为无限以及它可能带来什么影响的详细信息,请参阅另一个答案,它比我的方法更好。
答案 2 :(得分:1)
“ulimit -s unlimited”让堆栈无限增长。如果你通过递归编写程序,这可能会阻止你的程序崩溃,特别是如果你的程序不是尾递归(编译器可以“优化”那些),并且递归的深度很大。
@seisvelas的回答几乎包含了问题的正确答案。然而,它被埋藏在众多虚假声明中 - 见评论。因此,我觉得有必要写下这个答案。