- ベストアンサー
C++のスタック管理
大きめの配列(2Mくらい)を宣言するとスタックオーバーフローのエラーが発生します。で、配列をstaticにしたらエラーが発生しなくなりました。 なんとなく、初期に大きいバッファを確保するならOKで実行時に確保するとNGなのかな~と思っているのですが、このあたりのことを教えていただけないでしょうか。 なんとなく2Mくらいでオーバーフローが出るのも納得できません。 よろしくお願いします。 環境:VC++ .Net + winXP
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
2Mの配列を宣言というと void method(){ char a[20000000]; .... } という感じでしょうか。 C/C++言語のメモリは、大きく4つに分かれます。 (1)コード(プログラム)が記録されている領域。 (2)静的記憶領域。(文字列リテラル等が記憶されている領域) (3)スタック領域。 (4)ヒープ領域。 (1)、(2)はこの際関係ないので置いといて、 関数やメソッドの中でふつうに(staticをつけずに) 変数を宣言したとき、そのデータはスタック領域に置かれます。 これに対し、関数の外(グローバル変数)の変数、 static宣言した変数、malloc()で確保したメモリ、 newで作成したオブジェクトは、 ヒープ領域に置かれます。 スタック領域とヒープ領域を比べた場合、 ヒープ領域の方がはるかに大きいのです。 その代わり、スタックの方が効率的にアクセスできるようになっています。 スタック領域は一等地なのです。 山手線沿線に飛行場が作れないのと同じで、 スタックにあまり大きなメモリを確保することは出来ません。 なので、関数・メソッドの中の非static変数(自動変数)に 大きなメモリ領域を確保するのはタブーになっています。
その他の回答 (3)
- neko3839
- ベストアンサー率37% (100/269)
コンパイラ、リンカのオプションに「スタック サイズの設定」というのがありませんか? VC++.NET は未確認ですが、VC++ 6.0はMSDNのCD-ROMを見るとデフォルト値が1MBとされているようです。 コンパイラ、リンカのオプションでスタックサイズを大きめにするのも1つの対応ではあります。 C++であればnew演算子を使った方が良いと思います。
お礼
オプションがあるんですね。 ちょっと今探しても見つからなかったのですが、 6.0にあるならNETにもあると思いますのであとでもう少し探して見ます。 ありがとうございました。
- neko3839
- ベストアンサー率37% (100/269)
スレッド内で使える「スタックサイズ」には制限があります。 上記を自動変数で確保しているなら「スタックオーバフロー」します。 C++の場合は、new で確保してください。
お礼
mallocやnewでの確保も考えたのですが、4次元の配列なので、のちのち(クラスヘッダーを見たときに)分かりやすいと思い、配列での宣言としていました。 newで確保するほうが良いのでしょうか・・。
- t_nojiri
- ベストアンサー率28% (595/2071)
UNIXなら、1プロセスが確保できるメモリがカーネルパラメータで定義されてるのですが。 windowsは、うーん、msdn探してみるとかですか。
お礼
まさに知りたいことで、勉強になります。 スタックとヒープがごっちゃになっていました。 回答いただいたようなことだったんですね。 ありがとうございました。