関数呼び出しでのスタック消費量

このQ&Aのポイント
  • C++で関数を再帰呼び出しするとスタックオーバーフローとなりました。
  • 一回の呼び出しでスタックをe0(224)バイト使用してるようです。
  • なぜ(何に)こんなにも多く使うのでしょうか?
回答を見る
  • ベストアンサー

関数呼び出しでのスタック消費量

C++で関数を再帰呼び出しするとスタックオーバーフローとなりました。 それで、どれ位なら可能か調べるため、次の関数で試してみました。 int null(void) {  int a;  return null(); } 結果は次の通りでした。 1回目 &a 0x001cf9d4 2回目 &a 0x001cf8f4 3回目 &a 0x001cf814 よって、一回の呼び出しでスタックをe0(224)バイト使用してるようです。 なぜ(何に)こんなにも多く使うのでしょうか? 環境は、Vista Home Premium、Microsoft Visual C++ 2010 Express です。

質問者が選んだベストアンサー

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

アセンブリ出力見ればよいだけではないかと.

fusem23
質問者

お礼

さっそく見てみました。 int null(void) { push ebp mov ebp,esp sub esp,0CCh push ebx push esi push edi lea edi,[ebp-0CCh] mov ecx,33h mov eax,0CCCCCCCCh rep stos dword ptr es:[edi]  int a;  return null(); call null } pop edi pop esi pop ebx add esp,0CCh cmp ebp,esp call __RTC_CheckEsp mov esp,ebp pop ebp ret pushされてるのは、eip, ebp, ebx, esi, ediの5つで20バイト。 それ以外にcc(204)バイトが使われているようですね。 定数で埋め尽くされることと、変数1つで大きさが12バイト変化するので、デバッグ用だろうと推定しました。 が、具体的に何に使われてるかは不明ですね。 回答ありがとうございました。

その他の回答 (2)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

__RTC_CheckEsp という名前でちょろっと検索かけてみると, オーバーランなんかのチェックみたいですね.

参考URL:
http://www.glamenv-septzen.net/view/693
fusem23
質問者

お礼

その関数はこうなってました。 消費されてる領域とは、直接の関係はないようです。 回答ありがとうございました。 __RTC_CheckEsp: jmp _RTC_CheckEsp _RTC_CheckEsp: jne esperror ret

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.1

releaseビルドかdebugビルドかでも変わりますが、ローカル変数だけでなく戻り番地とかレジスタを退避するのでスタックフレームのサイズは大きいです。あとコンパイルがC++かC言語かとか呼出規約がcdeclやstdcallなのかとかでも変わると思います。 「コールスタック - Wikipedia」 http://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%BC%E3%83%AB%E3%82%B9%E3%82%BF%E3%83%83%E3%82%AF 「呼出規約 - Wikipedia」 http://ja.wikipedia.org/wiki/%E5%91%BC%E5%87%BA%E8%A6%8F%E7%B4%84

fusem23
質問者

お礼

そうか~、最近レジスタは多いですからね。 問題が起こってるのはdebugビルドです。 ありがとうございました。

関連するQ&A

  • VC++ 再帰呼び出しについて

    VC++6.0にてプログラミングを行っているものですが、 関数の再帰呼び出しについて質問です。 再帰呼び出しの際にスタックに積まれる変数というのは、 再帰呼び出しをする関数に渡す引数のことですか? スタックオーバーフローを起こさないために、 staticなポインタにHeap領域上の 変数を割り当てるとよい。 と分かったのですが、 この意味は、例えば static int *a = new int; ということなのですか?

  • 再帰関数を使うとき、ソフトウェアスタックはハードウェアスタックと比べてどれくらい遅い?

    再帰を使って関数を書こうと思うのですが、再帰する回数が不明なので、スタックオーバーフローを避けるためソフトウェアスタックを使おうと思っている者です。 ソフトウェアスタックはどれくらい遅いのでしょうか? どう実装すれば速度が改善されるのでしょうか?

  • 再帰呼び出しの計算量

    再帰呼び出しを用いた関数の計算量を求める方法がわからないので質問させていただきます. xのn乗を再帰呼び出しを用いて求める関数に関して,計算量を求める問題なのですが,どのような方針で求めればよいのでしょうか? int exponent(int x, int n) {   if(n == 0){     return 1;   }else{     return x * exponent(x, n-1);   } } exponentがn回呼ばれるからO(n)というのは間違いでしょうか?

  • c言語の関数定義について

    次の関数定義を考える. int f(int x) {if (x > 0) {return x * f(x-1);} else {return 1;} } この関数f と働き(すなわち,引数と戻り値の関係)が同じで再帰呼出(recursive call) を使わない関数g をC で定義せよ.ただし,オーバーフロー(overflow) については考慮しなくてよい. ”この関数f と働き(すなわち,引数と戻り値の関係)が同じで再帰呼出(recursive call) を使わない関数g をC で定義せよ”って理解できません、どのように定義したいいか、ご教授お願いします。

  • C# 再帰よるスタックオーバーフローについて

    VB2008 C# でプログラムしていますが、 プログラムで再帰を多く行わなくてはならず、 スタックオーバーフローが出てしまいます。 スタックオーバーフローを解決するためには、アルゴリズムを変更し、 再帰の回数を減らすしか方法はないのでしょうか? もしスタックの上限を変更する方法などがありましたら教えてください。 VBは初心者なので、なるべく簡単にお願いします。

  • 関数呼び出しについて質問です

    関数呼び出しについて質問です 私は今以下の様なプログラムを作成し実行しました #include <stdio.h> int i = 1; void infinity(void) { printf("%010d\n",i++); infinity(); } void main() { infinity(); } 関数を無限に呼び出すプログラムです 私が使っているパソコンでは4721回関数呼び出しができました そこで質問なのですが 1関数呼び出しは有限回であることがわかったが他のパソコンと比べるとどのくらいの差になるのか? 2関数呼び出し回数の上限は何によって(OS、ソフト)決められているのか? この2つお願いします

  • bsearch関数の呼び出しで

    C言語の深いところまで理解しようとしてます。今まで使わないだろうと思っていた関数へのポインタ なのですが、 2分探索のところで bsearch関数というのが出てきました。 この関数は第5引数に比較関数を引数にするのですが p = bsearch(&ky, x, nx, sizeof(int), (int (*)(const void *,const void *))int_cmp ); という形でサンプルソースには載っています。 この (int (*)(const void *,const void *))int_cmp の部分なのですが、まず戻り値をキャストするなら int (*)ではなく(int *)ではないでしょうか。 それとint_cmpは比較関数なのですが、引数が左側に来る、というところが納得できません。 ちなみにソースファイルをcppのままだとコンパイルできませんでした.cに拡張子を直したらコンパイルできました。 説明が足りないところがあったら指摘してください。お願いします。

  • 再帰呼び出しについて(基本)

    #include <stdio.h> void dan(int i); void kuku(void); void dan(int i) { int j; for (j = 1; j <= 9; j++) printf("%3d", i*j); putchar('\n'); } void kuku(void) { int i; for (i = 1; i <= 9; i++) dan(i); } int main(void) { kuku( ); return(0); } というプログラムがあるのですが、danとkukuを再帰呼び出しにしたいのですが、再帰の仕方がまったく分かりません。 知り合いに聞くと、両関数の引数を1つずつ増やすとよいと言われたのですが、手をつけられない状態です。 よろしくご教授お願いします。

  • 最大スタックサイズを大きくすることの影響は?

    再帰呼び出しを行うプログラムでスタックオーバーフローが発生するようになりました。 そこで最大スタックサイズを変更しようと考えていますが 最大スタックサイズを大きくすることで何か影響があることはあるのでしょうか? 他アプリ等に影響が出ないかを懸念しています。 ※最大スタックサイズは最大で16Mらしく、現在は1Mです。  特に影響がないのであれば最初から16Mにしておけば良いような気もして疑問に思っています。

  • 再帰呼び出しになってしまうのをループの形にしたい

    VBで繰り返して実行するプログラムを作ったのですが、 スタック領域をオーバーしてしまいます。 再帰呼び出しになっているのはわかったのですが、 改善ができません。 簡略したら下記のような状態でした。 Sub test1()  test2 End Sub Sub test2()  test1 End Sub このtest1を実行して、繰り返し作動するようにしたのですが、 当然スタックオーバーフローになります。 簡単にループに変形できるのでしょうか?

専門家に質問してみよう