web-dev-qa-db-ja.com

CまたはRubyプログラムの場合、ulimitまたはMac OS Xのプロセスごとにスタックサイズを変更する方法

CプログラムまたはRubyプログラム(Cスタックを使用))のスタックサイズを設定する推奨方法は、Bashシェルで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>はシェル単位であり、初めて設定する場合は通常機能します。問題は、2回目に設定するとエラーが返される場合があることです)

17

どうやら http://lists.Apple.com/archives/scitech/2004/Oct/msg00124.html から取られたmac os xのスタックサイズには厳しい制限があります、それでもまだ本当かどうかはわかりませんが、設定するには、ulimit -s hard、65532、または約65 megを呼び出すだけです。

Snow Leopard 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を設定すると、下げることはできず、上げることはできません。

11
Samy Vilar

私の考えでは、受け入れられた答えは完全に正しいものではなく、理解を誤ることにつながります。具体的には、最後の声明は真実ではありません。

limitを設定すると、下げることはできず、上げることはできません。

実際には、ソフト(ulimit -sまたはulimit -Ssで表示可能)とハード(ulimit -Hsで表示可能)の制限があります。ただし、ulimit -sを使用して制限を設定すると、ソフトおよびハード値に影響します。

hard limitを設定すると、値を下げることはできず、上げることはできませんが、値がハード制限より低いままであれば、ソフト制限を下げるか上げることができます。

これは動作します:

# 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
MisterFruits

システムのデフォルトのスタックサイズは、カーネルのバージョンによって異なります。私の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を必要に応じて使用できます。

1
jclin

/bin/zshの代わりに/bin/shを使用すると、このエラーがなくなることがわかりました。

私にとっては、ulimit -s unlimitedと呼ばれるシェルスクリプトでエラーが発生していました。スクリプトが/bin/shによって解釈されたとき(つまり、スクリプトファイルの最初の行として#!/bin/shがあったとき)、このエラーが発生しました。対照的に、zshを使用するように変更すると、すべてが正常に機能するように見えました。 zshunlimitedを「オペレーティングシステムが許容する最大の制限を与えて」と解釈するのに十分賢く、すべてが望みどおりに機能しました。

0
D.W.