スタックの制限


10

最近、OSが異なる3つのデバイスでスタックの制限をテストしました(制限とは、スタックが持つことができるレベルの最大数を意味します)。2^ 16レベルに達するたびに、オーバーフローエラー、および2 ^ 16-1を配置すると、正しく動作します。

だから私の質問は-それは本当ですか?スタックには、定義により最大値2 ^ 16-1がありますか、それともOSに依存しますか?


5
here i mean by limit the maximum number of levels that can the stack haveレベルは?
tkausl 2017年


3
どのようにテストしていますか?入力として2バイト(dword)を使用していますか?
pro3carp3 2017年

6
どのプログラミング言語を使用していますか?固定数でのこのような鋭い制限は、OSが割り当てたスタックサイズではなく、言語固有のランタイムによる意図的な制限であることを示しています。たとえば、Pythonはデフォルトで1000の制限を強制して、実際のスタックオーバーフローにぶつからないようにしています(実際のスタックオーバーフローからの回復は困難です)
CodesInChaos

回答:


20

これは、オペレーティングシステム固有(およびコンピューター固有)に強く依存しており、一部のOSでは、制限を構成する(さらには増やす)方法がいくつかあります。一部のコンパイラー(一部の限定された種類のCコード用の最近のGCCを含む)は、一部の末尾呼び出しを最適化できるため、コンパイラー固有(またはプログラミング言語実装固有)ですらあります

(一部のプログラミング言語仕様でR5RSなどの末尾呼び出しの最適化が必要です

あなたの質問が理にかなっているとは思えません(確かに2 16の制限ではありません)。私のLinuxデスクトップ(Debian / Sid / x86-64、Linux 4.9カーネル、32Gb RAM、Intel i5-4690S)では、最大8メガバイトのコールスタックがある場合があります(本当に必要な場合は、その制限を増やすことができます) )。

マルチスレッドASLRにより、質問がさらに複雑になっています。たとえばpthread_attr_setstack(3)を参照してください。スプリットスタックGoの実装でよく使用されます)と継続渡しのスタイルについてもお読みください。この回答もご覧ください。

価値があるものとして、次のC99(およびC11)コードを試してみました。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void recfun(int x, int d) {
  printf("start recfun x=%d d=%d\n", x, d);
  fflush(NULL);
  if (d>0)
    recfun(x+1, d-1);
  printf("end recfun x=%d d=%d\n", x, d);
}

int main(int argc, char**argv) {
  int md = argc>1?atoi(argv[1]):10000;
  printf ("start md=%d\n", md);
  recfun(0, md);
  printf("end md=%d clock=%ld µs\n", md, clock());
}    
// eof recur.c

そして、そのrecurプログラム(GCC 6をとしてコンパイルgcc -Wall -O recur.c -o recur)をrecur 161000 (2 16の制限をはるかに超えて)実行できました。それでrecur 256000また働いた。recur 456000(とクラッシュスタックオーバーフローレベルについてx=272057)。他のテストに対する忍耐力はありません。お使いのコンピュータでそれを試してください。最適化を依頼することを忘れないでください。

経験則(デスクトップ、ラップトップ、タブレットの場合)は、コールスタックを1メガバイト未満に保つことです。

また、渡すこと-fstack-usage gcc、私は次のようになってるrecur.su数字は、バイト単位での私の8Mbのスタックリミット直感と一致している(ファイルを、忘れないでmainやってたときに、カーネルがインストールされ、コール・フレームを、そしてもっと重要な初期スタックレイアウトはexecve(2 ) ...、crt0の場合):

 recur.c:5:10:recfun    32  static
 recur.c:13:9:main  16  static

PS。私のArduinoはありAtmega328、RAMの唯一の2Kバイトとするので、確かにその多くを再発することはできません。Arduinosで実際に可能なスタックフレームは数百個だけだと思います。


3

プロセスウィンドウのメインスレッドのスタックサイズは、リンカによって設定されます。デフォルトは1MBですが、/ STACKスイッチで調整できます。後で作成されたスレッドは、CreateThread関数のdwStackSizeパラメータを使用できます。

したがって、さまざまなWindows OSをテストしている場合、少なくともNT4.0以降、すべてデフォルトのスタックサイズが同じでした。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.