C语言 如何在 Mac OS X 上使用 ulimit 或每个进程为 C 或 Ruby 程序更改堆栈大小?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13245019/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to change the stack size using ulimit or per process on Mac OS X for a C or Ruby program?
提问by nonopolarity
It seems that the recommended way to set stack size for a C program or Ruby program (which uses the C stack), is by using ulimitin the Bash shell. But
似乎为 C 程序或 Ruby 程序(使用 C 堆栈)设置堆栈大小的推荐方法是ulimit在 Bash shell 中使用。但
$ ulimit -s
8192
$ ulimit -s 16384
-bash: ulimit: stack size: cannot modify limit: Operation not permitted
and sudodoesn't help either. Is there a way to set it to 16MB, 32MB, or 64MB? I thought there should be a way to set it per program invocation instead of setting a system wide parameter as well?
并且sudo也没有帮助。有没有办法将其设置为 16MB、32MB 或 64MB?我认为应该有一种方法可以为每个程序调用设置它而不是设置系统范围的参数?
Right now 8192probably means 8MB which is quite small, if that is compared to how much a process can be using, sometimes as much as 2GB of RAM.
现在8192可能意味着 8MB,这是非常小的,如果与一个进程可以使用的数量相比,有时多达 2GB 的 RAM。
(updated note:ulimit -acan show its current values).
(更新说明:ulimit -a可以显示其当前值)。
(update 2:it actually seems like ulimit -s <value>is per shell, and that if you set it the first time, it usually works. The problem is when you set it the second time, then it may return an error)
(更新2:它实际上似乎ulimit -s <value>是每个shell,如果你第一次设置它,它通常可以工作。问题是当你第二次设置它时,它可能会返回错误)
采纳答案by Samy Vilar
Apparently there is a hard limit on the stack size for mac os x, taken from http://lists.apple.com/archives/scitech/2004/Oct/msg00124.htmlgranted this is quite old, and Im not sure if its still true anymore, but to set it simply call ulimit -s hard, its 65532. or about 65 megs.
显然,mac os x 的堆栈大小有一个硬限制,取自http://lists.apple.com/archives/scitech/2004/Oct/msg00124.html授予这很旧,我不确定它是否仍然是正确的,但要设置它,只需调用 ulimit -s hard,它的 65532. 或大约 65 megs。
I did some tests on snow leopard, 10.6.8, and it does seem to be true.
我在雪豹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
$
I also found this http://linuxtoosx.blogspot.com/2010/10/stack-overflow-increasing-stack-limit.htmlthough I haven't test it, so can't really say much about it.
我也发现了这个http://linuxtoosx.blogspot.com/2010/10/stack-overflow-increasing-stack-limit.html虽然我没有测试过它,所以不能说太多。
When applications consume gigs of memory thats usually taken from the heap, the stack is usually reserve for local automatic variables that exist for a relatively small amount of time equivalent to the lifespan of the function call, the heap is where most of the persistent data lives.
当应用程序消耗通常从堆中获取的大量内存时,堆栈通常是为本地自动变量保留的,这些变量存在的时间相对较短,相当于函数调用的生命周期,堆是大多数持久数据所在的位置.
here is a quick tutorial:
这是一个快速教程:
#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 is only temporary you would have to update it every time, or update your corresponding bash script to set it automatically.
ulimit 只是暂时的,您每次都必须更新它,或者更新相应的 bash 脚本以自动设置它。
Once ulimit is set it can only be lowered never raised.
设置 ulimit 后,它只能降低永远不会升高。
回答by MisterFruits
To my mind the accepted answer is not totally right and leads to miss comprehension, more specifically the last statement is not true.
在我看来,接受的答案并不完全正确,会导致误解,更具体地说,最后一句话是不正确的。
Once ulimit is set it can only be lowered never raised.
设置 ulimit 后,它只能降低永远不会升高。
There are indeed soft (displayable with ulimit -sor ulimit -Ss) and hard (displayable with ulimit -Hs) limits.
But while setting the limit through ulimit -swill affect soft andhard values.
确实有软(可以用ulimit -s或显示ulimit -Ss)和硬(可以用 显示ulimit -Hs)限制。但是通过设置限制ulimit -s会影响软值和硬值。
Once hardlimit is set it can only be lowered never raise, but soft limit can be lowered or raised provided that the value stays lower than the hard limit.
一旦设置了硬限制,它只能降低永远不会提高,但只要值保持低于硬限制,就可以降低或提高软限制。
This will work:
这将起作用:
# 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
回答by jclin
The system default stack size varies from different version of kernel to kernel. My 10.7 is 16384, such that ulimit -s 16384 is accepted by my Mac. You can try sysctl kern.stack_sizeand it shows the read-only stack size. mine is 16384.
You can see this technical article, http://developer.apple.com/library/mac/#qa/qa1419/_index.html, to see how to change the default stack size for C program. For Ruby, because it's a scripting language, you have to enlarge its stack size during linking Ruby interpreter.
Excepting for having very deep function calls or recursion, or having very large array and objects being allocated in the stack, your program should not have huge stack space. Instead, using heap or dynamically allocation can use up to 2GB of RAM as you wish.
系统默认堆栈大小因内核版本而异。我的 10.7 是 16384,这样 ulimit -s 16384 就被我的 Mac 接受了。您可以尝试sysctl kern.stack_size,它会显示只读堆栈大小。我的是 16384。
你可以看这篇技术文章,http://developer.apple.com/library/mac/#qa/qa1419/_index.html,看看如何更改 C 程序的默认堆栈大小。对于 Ruby,由于它是一种脚本语言,因此在链接 Ruby 解释器时必须扩大其堆栈大小。除了具有非常深的函数调用或递归,或者在堆栈中分配非常大的数组和对象外,您的程序不应有巨大的堆栈空间。相反,使用堆或动态分配可以根据需要使用多达 2GB 的 RAM。
回答by D.W.
I found that using /bin/zshinstead of /bin/shmade this error go away.
我发现使用/bin/zsh而不是/bin/sh使此错误消失。
For me, the error was occurring in a shell script that called ulimit -s unlimited. When the script was interpreted by /bin/sh(i.e., had #!/bin/shas the first line of the script file), it barfed with this error. In contrast, when changing it to use zsh, everything seemed to work fine. zshwas smart enough to interpret unlimitedas "give me the largest limit the operating system will let me have", and everything worked as you'd want it to.
对我来说,错误发生在一个名为ulimit -s unlimited. 当脚本被解释/bin/sh(即,#!/bin/sh作为脚本文件的第一行)时,它会出现这个错误。相比之下,当将其更改为 use 时zsh,一切似乎都正常。 zsh足够聪明,可以解释unlimited为“给我操作系统允许我拥有的最大限制”,并且一切都如您所愿。

