关于堆栈分配有很多相关的问题是可以理解的
但是在各种 *nix 机器上,我可以发出 bash 命令
ulimit -s unlimited
或 csh 命令
set stacksize unlimited
这如何改变程序的执行方式?对程序或系统性能是否有任何影响(例如,为什么这不是默认设置)?
如果有更多的系统细节是相关的,我主要关心的是在 x86_64 硬件上运行的 Linux 上使用 GCC 编译的程序。
关于堆栈分配有很多相关的问题是可以理解的
但是在各种 *nix 机器上,我可以发出 bash 命令
ulimit -s unlimited
或 csh 命令
set stacksize unlimited
这如何改变程序的执行方式?对程序或系统性能是否有任何影响(例如,为什么这不是默认设置)?
如果有更多的系统细节是相关的,我主要关心的是在 x86_64 硬件上运行的 Linux 上使用 GCC 编译的程序。
当您调用函数时,会在堆栈上分配一个新的“命名空间”。这就是函数可以具有局部变量的方式。随着函数调用函数,函数又调用函数,我们不断在堆栈上分配越来越多的空间来维护这种深层的命名空间层次结构。
为了限制使用大量堆栈空间的程序,通常通过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 上)。
堆栈大小确实可以是无限的。_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
定义,如果它是无限的 - 它是无限的。有关将其设置为无限的含义以及它可能产生的影响的详细信息,请参阅另一个答案,它比我的要好得多。
ulimit -s unlimited
让堆栈无限增长。
This may prevent your program from crashing if you write programs by recursion, especially if your programs are not tail recursive (compilers can "optimize" those), and the depth of recursion is large.