VS2015のVC++で、指定可能なスタックサイズの上限値と、コンパイラ/リンカオプションで別に指定できる意図は?

[戻る]
もっこり 2016/02/15(月) 10:07:17
恐れ入りますが、タイトルの2つのお尋ねをさせて頂けないでしょうか。
予め調べたのですが、どうしても分からなかったので投稿させて頂いた次第です。どうぞ宜しくお願い致します。

A. コンパイラ/リンカ( 今回、EDITBIN.exe は除く )で編集できる、スタックサイズの上限値は?

   コンパイラオプションの説明
   https://msdn.microsoft.com/ja-jp/library/tdkhxaks.aspx に、[1,リンカの最大許容量]とある。

   リンカオプションの説明
   https://msdn.microsoft.com/ja-jp/library/8cxs58a6.aspx では触れられていない。

   ※ http://oshiete.goo.ne.jp/qa/4376527.html は16Mbyteとあるが、推測に過ぎない事・情報源・根拠が不明・古い、といった事から、参考にならない。

B. コンパイラ/リンカオプションで別に指定できる意味は?
   ↓から、細かい粒度で指定できるリンカオプションだけで十分に思える。わざわざコンパイラにも用意されている意図が不明。

   コンパイラ
   /Fオプション。4バイト単位で指定可。

   リンカ
   /STACKオプション。1バイト単位で指定可。

   又、別々に異なる値を指定した時の挙動が不明。実験したが、ビルド時の警告はなく、実行時の異常も無かった。

仲澤@失業者 2016/02/15(月) 20:43:35
EXEでコミットできるスタック量の上限が明記してあるのは見つけられませんでした。
ただ、上限(エラーが出る)は、
 1.実装してある物理メモリーに依存
 2.実行EXEの32/64プロセスタイプに依存
 3.OSの32bit/64bitに依存
など色々と依存するので、断言はしにくいのではないでしょうか。
また一般的には、まぁ減らす方向に考えるのが普通なので。
このあたりとかが参考になるかもしれません。

https://technet.microsoft.com/ja-jp/windows/mark_04.aspx

ちなみに16MByteというのは、0xFFFFFFFFで、
多分16bitCPU時代に SS:SP (スタックセグメント:スタックポインタ)
で表せる最大値のことかもしれません(とほい目)。

さて、両オプション件ですが、リンカーでコントロールできないのは問題があります。
一方、EXEでなく、LIBを作る場合、obj単位に必要なスタック量が
明示されているのは、あながち無駄とも言えないかもしれませんね。
あんま、役に立たなくてすみません。

tetrapod 2016/02/16(火) 10:54:57
「意図」なるものはオイラたちたんなる掲示板の読者に聞いても得られるはずが無くて
Microsoft に聞くしかないだろう。
まあ憶測することはできるがそれは正解ではない。

1.仮想メモリのページングやキャッシュというものには「ブロックサイズ」なる概念が
 あって、それに整合しないような指定をしても意味がない。
 1バイト単位でスタックサイズ指定ができても無視され 64KiB 単位になる
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686774(v=vs.85).aspx

2.普通のユーザはリンク操作もコンパイラドライバ cl.exe や gcc.exe で行う。
 なので cl.exe のオプションとしてスタックサイズ指定があるのは自然な話。
 link.exe でも指定可能なのは歴史的事情って奴だと思う。
 link と cl で指定の仕方が違うのも歴史的事情。
 Microsoft の過去との互換性維持のポリシーに乾杯。

3.スタックサイズに 400MiB を指定して動いている人がいる。
http://yaneuraou.yaneu.com/2016/01/03/
 「指定可能な上限」は無いのではないかと推測できる。
 ※ x86 ではユーザ用メモリ空間が 2GiB しか無いから大きくしすぎるのは無駄
 ※ Linux 系では ulimit でユーザがメモリ使用上限を制約できる

4. cl -F16384 hoge.c -link /stack:65536
 として dumpbin /headers hoge.exe で確認したら 65536 のほうが有効だった。
 このとき link.exe には /stack:16384 と /stack:65536 がこの順に渡されている。
 単に後から指定した数値のほうが採用されているだけだろう。

ITO 2016/03/01(火) 10:49:11
これ以上は目的を知らないと回答が難しいのでは?
まぁー、

通常、
 スタックエリアは、1MB固定で考えて、それ以上はnew等を使って確保する。
ですね。

組込みマイコン等でスタックエリアがシビアの場合は、インテル Cも考えたほうがいいで
すね

仲澤@失業者 2016/03/01(火) 11:18:19
本題と関係なくて申し訳ありませんが、
再起関数の様にネストするたびにスタックを必要とし、
かつ、その深さを予測するのが難しい場合もありますね。

古いスレッドには追加発言できません。