似乎为C程序或Ruby程序(使用C堆栈)设置堆栈大小的推荐方法是在Bash shell中使用ulimit
。但
$ ulimit -s
8192
$ ulimit -s 16384
-bash: ulimit: stack size: cannot modify limit: Operation not permitted
和sudo
也没有帮助。有没有办法将其设置为16MB,32MB或64MB?我认为应该有一种方法来设置每个程序调用,而不是设置系统范围的参数?
现在8192
可能意味着8MB这个非常小,如果将其与进程可以使用的数量进行比较,有时甚至高达2GB的RAM。
(更新后的注释: ulimit -a
可以显示其当前值。)
(更新2:它实际上似乎ulimit -s <value>
是每个shell,如果你第一次设置它,它通常会有效。问题是当你设置第二次时间,那么它可能会返回一个错误)
答案 0 :(得分:11)
显然,对于mac os x的堆栈大小有一个硬限制,取自http://lists.apple.com/archives/scitech/2004/Oct/msg00124.html,这已经很久了,我不确定它是否仍然是真的,但设置它只需调用ulimit -s很难,它的65532.或约65 megs。
我对雪豹进行了一些测试,10.6.8,看起来确实如此。
$ ulimit -a
...
stack size (kbytes, -s) 8192
...
$ ulimit -s 65533
-bash: ulimit: stack size: cannot modify limit: Operation not permitted
$ ulimit -s 65532
$
虽然我没有对它进行测试,但我也发现了这个http://linuxtoosx.blogspot.com/2010/10/stack-overflow-increasing-stack-limit.html,因此无法真正说出来。
当应用程序消耗通常从堆中获取的内存时,堆栈通常为本地自动变量保留,这些变量存在的时间相当于函数调用的生命周期,堆是大多数的持久的数据生活。
这是一个快速教程:
#include <stdlib.h>
#define NUMBER_OF_BYTES 10000000 // about 10 megs
void test()
{
char stack_data[NUMBER_OF_BYTES]; // allocating on the stack.
char *heap_data = malloc(NUMBER_OF_BYTES); // pointer (heap_data) lives on the stack, the actual data lives on the heap.
}
int main()
{
test();
// at this point stack_data[NUMBER_OF_BYTES] and *heap_data have being removed, but malloc(NUMBER_OF_BYTES) persists.
// depending on the calling convention either main or test are responssible for resetting the stack.
// on most compilers including gcc, the caller (main) is responssible.
return 0;
}
$ ulimit -a
...
stack size (kbytes, -s) 8192
...
$ gcc m.c
$ ./a.out
Segmentation fault
$ ulimit -s hard
$ ./a.out
$
ulimit只是暂时的,您每次都必须更新它,或者更新相应的bash脚本以自动设置它。
设置ulimit后,只能降低从不提升。
答案 1 :(得分:2)
在我看来,接受的答案并不完全正确,导致错过理解,更具体地说,最后的陈述是不正确的。
设置ulimit后,只能降低从不提升。
确实有软(可显示ulimit -s
或ulimit -Ss
)和硬(可显示ulimit -Hs
)限制。
但是,通过ulimit -s
设置限制会影响软和硬值。
设置硬限制后,只能降低永不升高,但只要该值低于硬限制,就可以降低或提高软限制。
这将有效:
# base values
$ ulimit -s
100
$ ulimit -Hs
100
$ ulimit -Ss
100
# lower soft limit only
$ ulimit -Ss 50
$ ulimit -s
50
$ ulimit -Hs
100
$ ulimit -Ss
50
# raise soft limit only
$ ulimit -Ss 100
$ ulimit -s
100
$ ulimit -Hs
100
$ ulimit -Ss
100
# lower soft and hard limit
$ ulimit -s 50
$ ulimit -s
50
$ ulimit -Hs
50
$ ulimit -Ss
50
# then impossible to raise soft limit due to hard limit
$ ulimit -s 100
-bash: ulimit: stack size: cannot modify limit: Operation not permitted
$ ulimit -Ss 100
-bash: ulimit: stack size: cannot modify limit: Invalid argument
答案 2 :(得分:1)
系统默认堆栈大小因内核的不同版本而异。我的10.7是16384,因此我的Mac接受了ulimit -s 16384。您可以尝试sysctl kern.stack_size
并显示只读堆栈大小。我的是16384
您可以看到此技术文章http://developer.apple.com/library/mac/#qa/qa1419/_index.html,以了解如何更改C程序的默认堆栈大小。对于Ruby,因为它是一种脚本语言,所以在链接Ruby解释器时必须扩大其堆栈大小。
除了非常深的函数调用或递归,或者在堆栈中分配了非常大的数组和对象之外,您的程序不应该有很大的堆栈空间。相反,使用堆或动态分配可以根据需要使用最多2GB的RAM。
答案 3 :(得分:0)
我发现使用/bin/zsh
代替/bin/sh
会导致此错误消失。
对我来说,错误发生在名为ulimit -s unlimited
的shell脚本中。当脚本由/bin/sh
解释时(即,#!/bin/sh
作为脚本文件的第一行),它会出现此错误。相反,当将其更改为使用zsh
时,一切似乎都能正常工作。 zsh
非常聪明,可以将unlimited
解释为“给我操作系统允许的最大限制”,并且一切都按照您的意愿运行。