-
Notifications
You must be signed in to change notification settings - Fork 0
MS_ThreadStack
-
TOP > インフラストラクチャ > 仮想メモリ管理
- 仮想アドレス空間の確保のAPI
- スレッドのスタック
-
スタック・オーバーフローはなぜ起きるのか?と言えば、
OSが確保したスレッドのスタックが、再帰呼出し等によって、領域超過を起こすため。 -
スレッドのスタックには、
- 各関数のスタック・フレームが
- 引数、戻り値、ローカル変数
- 戻り先の呼出し元へのポインタ
- 各関数の呼出し履歴分
積まれることになる。
- 各関数のスタック・フレームが
基本的に 1 スレッド 1MB のメモリ(アドレス空間)を消費する。
スレッドのスタックのメモリ予約・確保については、
- OS がスレッド作成時にスタックを予約する(基本 1MB)。
- OS が関数呼び出しの際にスタックを積む(コミット)。
という動作になる。ユーザによる制御は不要。
スタックの最上位のページは既にコミットされており、
スタックに最上位まで積まれ二重にコミットしようとした場合に
スタックオーバーフローという例外が発生する。
移行メモ: ここで言う「最上位のページ」は、 スタック末端に置かれる ガード ページのこと。 スタックが伸びてガード ページに触れると、OS が次のページをコミットして ガード ページをひとつ下へずらす。 予約領域の末端まで達し、もうずらせなくなった時点で スタック オーバーフロー(
STATUS_STACK_OVERFLOW)になる。
スタックの成長はメモリの成長とは(アドレス空間から)逆方向になる。
- メモリの成長 : 0 → 4GB(16TB) の方向
- スタックの成長 : 4GB(16TB) → 0 の方向
※ 関数の呼び出し規則によって積まれ方の詳細は若干違う。
-
/STACKのリンカ・オプションで予約サイズなどを変更可能。 - EDITBIN ツールを使用して変更可能(ビルド済みの EXE に対して)。
- .NET では
ThreadのコンストラクタでmaxStackSizeを指定できる
(ただしメイン スレッドには適用されない)。
IIS 上ではスタック・サイズが小さいらしい。
※ このため、開発時(コンソール/WinForms)では通らないのに
IIS 上でのみスタック オーバーフローする、という現象が起こりうる。
深い再帰はループへ書き換えるのが確実な対処。
-
Issue #341 · OpenTouryoProject/OpenTouryo
Change the implementation of recursion to loop for suppress stack overflow in BaseDam.
補足: .NET では
StackOverflowExceptionはキャッチできない (.NET 2.0 以降、プロセスが即座に終了する)。try/catchで握り潰す設計はできないため、 再帰の深さを設計時に抑えるしかない。
Tags: Windows, メモリ管理, 障害対応, 性能, デバッグ
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。