[英]How to get current thread's stack size via C API on Mac OS X? (no Cocoa or carbon)
[英]How to change the stack size using ulimit or per process on Mac OS X for a C or Ruby program?
似乎為 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,如果你第一次設置它,它通常會起作用。問題是當你第二次設置它時,它可能會返回錯誤)
顯然,對於mac os x的堆棧大小有一個硬性限制,取自http://lists.apple.com/archives/scitech/2004/Oct/msg00124.html,這已經很老了,我不確定它是否是仍然是真的,但設置它只是調用ulimit -s hard,它的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,它只能降低從不升高。
在我看來,接受的答案並不完全正確,導致錯過理解,更具體地說,最后的陳述是不正確的。
一旦設置了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
系統默認堆棧大小因內核的不同版本而異。 我的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。
我發現用/bin/zsh
代替/bin/sh
使得這個錯誤消失了。
對我來說,錯誤發生在一個調用ulimit -s unlimited
的shell腳本中。 當腳本被/bin/sh
解釋時(即,將#!/bin/sh
作為腳本文件的第一行),它會發生此錯誤。 相比之下,當改變它使用zsh
,一切似乎都很好。 zsh
很聰明,可以將unlimited
解釋為“給我操作系統讓我擁有的最大限制”,並且一切都按照你的意願運行。
內置ulimit
控件的所有限制實際上在操作系統 kernel 中實現,因此您應該看到整個系統的 C 接口文檔。 這是setrlimit()
的 Apple 文檔: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setrlimit.2.html
(請注意,該文檔的路徑似乎是 iPhoneOS,但內容仍然是“Mac OS X”。如果您在本地安裝了合適的文檔,在終端中運行man setrlimit
應該會發出最新的文檔。)
新創建的進程從fork()
父進程或執行exec()
的前一個進程繼承限制。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.