2012-02-03 17 views
4

C言語で関数を記述しましたが、呼び出されるとすぐにスタックのオーバーフローが発生します。C関数呼び出しのスタックオーバーフロー - MS Visual C++ 2010 Express

プロトタイプ: void dumpOutput(Settings *, char **, FILE *);

ライン呼び出し:それを呼び出す時に dumpOutput(stSettings, sInput, fpOut);

を、stSettingsは既にSettings構造、sInputへのポインタである動的に割り当てられた2次元アレイとfpOutFILE *です。それは、エラーやメモリリークなどなく、呼び出し元の行まで届きます。

実際の関数はかなり時間がかかっています。ここでは、コードが関数に入ると同時にオーバーフローが発生します

私は渡された引数に問題があるかどうかをチェックするのにダミー変数を使ってmain()から直接同じ関数を呼び出そうとしましたが、それでもスタックオーバーフロー条件がスローされました。

エラーは、関数が呼び出されたときにchkstk.asmから発生します。このasmファイル(そこにあるコメントに従う)は、呼び出された関数のメモリをチェック/アロケートするためにスタックを調べようとします。スタックオーバーフローが発生するまで、ちょうどFind next lower page and probe部分にジャンプし続けます。

dumpOutputのローカル変数は、メモリビーストではなく、ちょうど6つの整数と2つのポインタです。

この関数を入力する時点のコードで使用されるメモリは60,936Kで、スタックオーバーフローが発生した時点で61,940Kに増加します。このメモリの大部分はsInputに入っています。これがエラーの原因ですか?ポインタだけが渡されているので、私はそうは思わない。第二に、なぜdumpOutputがスタック上に1004Kのメモリを割り当てようとしているのか理解できないのですか?

私は完全にここに迷っています。どんな助力も高く評価されます。

ありがとうございます。

+0

あなたはスタックオーバーフローのためにグーグルでこのサイトを見つけましたか? – CashCow

+0

dumpOutput()はsInput配列のサイズをどのように知っていますか?ダンプするデータの最後にコードを終了できませんでしたか? FILEに書き込まれるたびに各バイトをフラッシュして、どのくらいのデータが書き込まれ、期待通りのものであるかを確認することができます。 – peterept

+0

引数はすべてポインタであるため、スタック上の3 * 8(64ビットシステム上)バイト以上のメモリが必要です。関数の最初の数行を質問に追加できますか?そしておそらく引数の完全な宣言、そしてそれの前の実際の呼び出しといくつかの行? –

答えて

4

を見ずに答えるのは難しい、スタックオーバーフロー例外を発生させるために_chkstk()さん仕事です。生成されたマシンコードを調べることで診断することができます。関数にステップインした後、編集ウィンドウを右クリックし、[逆アセンブリに移動]をクリックします。 EAXレジスタを介して渡された値が重要なものです、それはあなたの関数が必要とするスタック領域の量です

003013B0 push  ebp 
003013B1 mov   ebp,esp 
003013B3 mov   eax,1000D4h     ; <== here 
003013B8 call  @ILT+70(__chkstk) (30104Bh) 

:あなたは、これに似た何かを見るべきです。 Chkstkはスタックのページを調べることによって実際に利用可能であることを確認します。あなたが繰り返しループしているのを見たら、コード内のEAXの値が高いです。私のように、スタックのすべてのバイトを消費することが保証されています。もっと。どちらが保護されているかは、アクセス違反例外が発生します。しかし、保証はありません。あなたのコードは、ヒープに属するマップされたページに誤って書き込む可能性があります。それはバグを診断するのが非常に困難です。 Chkstk()は、欲求不満で脳を吹く前に、これらのバグを見つけるのを助けます。

私は単純に、この小さなテスト機能でそれをやった:

void test() 
{ 
    char kaboom[1024*1024]; 
} 

私たちはあなたを見ることはできませんが、例外はあなたのいずれかがローカル変数として大きな配列を持っているか、あなたは大きな値を渡していると言います_alloca()へ。その配列を代わりにヒープから割り当てることで修正してください。

+0

助けてくれてありがとう。私の場合、eaxは437014hとなり、確かに大きかった。私は誤って非常に大きなサイズを持っていた別のローカルアレイを見落としていたことが判明しました。それを固定して問題を解決しました! もう一度ありがとう!あなたは揺れる! :) – xenodevil

0

ほとんどの場合、スタックの破損や再帰エラーが、それは設計により任意のコード

+0

再帰はありませんが、非常に大きな配列のためスタックの破損でした。ご協力ありがとうございました! :) – xenodevil

関連する問題