"ulimit -s unlimited"有什么作用?

Bri*_*ins 44 linux stack ulimit

有关堆栈分配的许多相关问题是可以理解的

堆栈和堆的内容和位置是什么?

为什么堆栈大小有限制?

堆栈和堆内存的大小

但是在各种*nix机器上,我可以发出bash命令

ulimit -s unlimited
Run Code Online (Sandbox Code Playgroud)

或者csh命令

set stacksize unlimited
Run Code Online (Sandbox Code Playgroud)

这如何改变程序的执行方式?是否对程序或系统性能有任何影响(例如,为什么这不是默认值)?

如果更多的系统细节是相关的,我主要关注在x86_64硬件上运行的Linux上使用GCC编译的程序.

Ale*_*lex 25

调用函数时,会在堆栈上分配新的"命名空间".这就是函数可以有局部变量的方式.随着函数调用函数,函数又调用函数,我们不断在堆栈上分配越来越多的空间来维护命名空间的深层次结构.

为了使用大量的堆栈空间来限制程序,通常会通过限制来实现限制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.
Run Code Online (Sandbox Code Playgroud)

通常,使用大量的堆栈空间是偶然的或非常深的递归的症状,可能不应该如此依赖堆栈.因此堆栈限制.

对绩效的影响很小但确实存在.使用该time命令,我发现消除堆栈限制会使性能提高几分之一秒(至少在64位Ubuntu上).

  • @Maxwell其次,超过堆栈大小是堆栈粉碎的完全不同的问题.当堆栈溢出发生时,内核会终止进程,就是这样.堆栈中没有任何内容写入,不会产生任何损害(除了进程终止). (6认同)
  • @BasileStarynkevitch该死的.我认为这一点非常明确.如果你想让gcc没有优化掉堆栈粉碎教育过期,只需用`gcc -O0`编译它. (5认同)
  • @Maxwell两个错误:堆栈大小限制与防止"整个系统"崩溃无关.RAM是RAM,决定如何为堆栈或堆映射它是内核的工作.制作一个100GB的堆栈并不比在堆上分配100GB更有害:操作将失败(sbrk或exec失败),或者存在过度使用,并且当你使用内存直到系统可以遵守它时,进程将被终止记忆承诺再次.在任何一种情况下,整个系统的完整性都是安全的.一个进程无法击败内核. (3认同)
  • 这个答案是完全错误的.Linux上的每个进程都有自己的堆栈 - 没有系统堆栈空间.堆栈在x86上向下增长,当堆栈顶部(物理上是堆栈内存的底部)达到预设限制或满足另一个内存映射时,会发生溢出.堆栈缓冲区溢出发生在相反的方向.如果堆栈会向上增长,则很难覆盖返回地址. (3认同)
  • 使用`gcc-4.7 -O3`,你的`smash_the_stack` 示例是尾递归的,被转换为没有任何调用的无限循环。 (2认同)
  • @BasileStarynkevitch编译器这么聪明.我改变了这个例子,让gcc更难以优化,对不起! (2认同)

Abh*_*and 5

ulimit -s unlimited让堆栈无限增长。

如果您通过递归编写程序,这可能会防止您的程序崩溃,特别是如果您的程序不是尾递归(编译器可以“优化”它们),并且递归深度很大。