あなたはその選択をした男を見ています。David Cutlerと彼のチームは、デフォルトのスタックサイズとして1メガバイトを選択しました。.NETやC#とは何の関係もありません。これは、Windows NTを作成したときに明らかにされました。1メガバイトは、プログラムのEXEヘッダーまたはCreateThread()winapi呼び出しでスタックサイズが明示的に指定されていない場合に選択されます。これは通常の方法であり、ほとんどすべてのプログラマーがOSに任せてサイズを選択します。
その選択はおそらくWindows NTの設計よりも古いものであり、歴史はこれについてあまりに曖昧です。カトラーがそれについて本を書いてくれればいいのですが、彼は作家ではありませんでした。彼はコンピューターの動作に非常に影響力を持っています。彼の最初のOS設計は、RSC-11Mで、DECコンピュータ(Digital Equipment Corporation)向けの16ビットオペレーティングシステムでした。これは、8ビットマイクロプロセッサ用の最初のまともなOS、Gary KildallのCP / Mに大きな影響を与えました。これはMS-DOSに大きな影響を与えました。
彼の次の設計は、仮想メモリをサポートする32ビットプロセッサ用のオペレーティングシステムであるVMSでした。大成功です。彼の次のものは、会社が崩壊し始めた頃にDECによってキャンセルされ、安価なPCハードウェアと競争することができませんでした。マイクロソフトをキューに入れて、彼らは彼に彼が拒否することができない申し出をしました。彼の同僚の多くも参加しました。彼らはWindows NTとして知られているVMS v2に取り組みました。DECはそれについて動揺しました、それを解決するためにお金が手を変えました。VMSがすでに1メガバイトを選択しているかどうかは、私にはわかりませんが、RSX-11を十分に理解しているだけです。ありそうです。
十分な歴史。1メガバイトは多く、実際のスレッドが数キロバイトを超えることはめったにありません。したがって、メガバイトは実際にはかなり無駄です。ただし、メガバイトは仮想メモリにすぎないので、デマンドページの仮想メモリオペレーティングシステムでは、このような無駄を省くことができます。4096バイトごとに1つずつ、プロセッサに番号を付けます。実際にアドレスを指定するまで、物理メモリ、つまりマシンのRAMを実際に使用することはありません。
1メガバイトのサイズは、もともとネイティブプログラムに対応するために選択されていたため、.NETプログラムではそれは過剰です。大きなスタックフレームを作成する傾向があり、文字列とバッファ(配列)もスタックに格納します。マルウェアの攻撃ベクトルとして悪名高いバッファオーバーフローは、データを使用してプログラムを操作できます。.NETプログラムの動作方法ではなく、文字列と配列がGCヒープに割り当てられ、インデックスがチェックされます。C#でスタックにスペースを割り当てる唯一の方法は、安全でないstackallocキーワードを使用することです。
.NETでのスタックの重要な使用法は、ジッターだけです。スレッドのスタックを使用して、MSILをマシンコードにジャストインタイムでコンパイルします。必要なスペースを確認したことはありません。コードの性質とオプティマイザが有効になっているかどうかによって異なりますが、数十キロバイトはおおよその目安です。それ以外の場合は、このWebサイトの名前が付けられました。.NETプログラムのスタックオーバーフローは非常に致命的です。例外をキャッチしようとするコードを確実にJITするのに十分なスペース(3キロバイト未満)が残っていません。デスクトップへのKaboomが唯一のオプションです。
最後に重要なことですが、.NETプログラムはスタックに対してかなり非生産的なことを行います。CLRはスレッドのスタックをコミットします。これは高価な言葉です。つまり、スタックのサイズを予約するだけでなく、オペレーティングシステムのページングファイルにスペースが確保されるため、必要に応じてスタックを常にスワップアウトできます。コミットに失敗すると致命的なエラーとなり、無条件にプログラムが終了します。これは、RAMが非常に少なく、実行するプロセスが多すぎるマシンでのみ発生します。このようなマシンは、プログラムが終了する前に糖蜜に変換されます。15年以上前の問題であり、今日ではありません。F1レースカーのようにプログラムを調整するプログラマー<disableCommitThreadStack>
は、.configファイルの要素を使用します。
Fwiw、Cutlerはオペレーティングシステムの設計をやめませんでした。その写真は、彼がAzureに取り組んでいる間に作成されました。
更新。.NETがスタックをコミットしないことに気付きました。いつ、なぜこれが起こったのか正確にはわかりません。この設計変更は.NET 4.5のどこかで起こったと思います。かなり賢明な変更。
Thread
コンストラクタの適切なオーバーロードを使用してスタックサイズを指定することもできます。しかし、これは疑問を投げかけます、なぜより大きなスタックが必要なのですか?