6

これは私の質問のトピックがフォーラムの名前に似ているという偶然の一致だと思われるかもしれませんが、実際には「スタックオーバーフロー」という用語をグーグルで検索してここに到達しました。

Cを使用してプログラムするOPNETネットワークシミュレータを使用しています。大きな配列サイズで問題が発生していると思います。ある種のメモリ割り当ての制限に直面しているようです。それは、OPNET、Windows、私のラップトップメモリ​​、またはおそらくC言語に関係している可能性があります。この問題は、要素の総数が数千の整数になるネストされた配列を使用しようとすると発生します。全体的なメモリ割り当ての制限を超えていると思います。この上限を増やす方法があるかどうか疑問に思っています。正確な問題の説明は次のとおりです。

私は基本的にルーティングテーブルを持っています。これをrouting_tbl[n]と呼びましょう。これは、30ノード(ルーター)をサポートしていることを意味します。ここで、このテーブルの各ノードについて、情報を保持します。path [p]と呼ばれる配列内の、約数百(数百)の使用可能なパス。繰り返しますが、この配列の各パスについて、それに属するノードのリストをhops[h]という配列に保持します。したがって、少なくともnph整数に相当するメモリを使用していますが、このテーブルには他の情報も含まれています。同じ関数で、ほぼ40,000個の整数を消費する別のネストされた配列も使用しています。シミュレーションを実行するとすぐに、スタックオーバーフローについての文句を言うのをやめます。ルーティングテーブルの合計サイズを小さくすると機能します。何が問題を引き起こしていると思いますか、そしてそれをどのように解決することができますか?アリに感謝します

4

6 に答える 6

10

コードを投稿すると役立つ場合があります。質問を編集して、問題の機能とエラーを含めます。

一方、非常に一般的な答えは次のとおりです。

スタック オーバーフローの 2 つの主な原因は、1) 再帰関数、または 2) 多数のローカル変数の割り当てです。

再帰

関数が次のように自分自身を呼び出す場合:

int recurse(int number) {

    return (recurse(number));
}

ローカル変数と関数の引数はスタックに格納されるため、スタックがいっぱいになり、スタック オーバーフローが発生します。

大きなローカル変数

大量のローカル変数の配列を割り当てようとすると、簡単にスタックをオーバーフローさせることができます。このような関数は問題を引き起こす可能性があります:

void hugeStack (void) {

    unsigned long long reallyBig[100000000][1000000000];

    ...
}

この同様の質問に対する非常に詳細な回答があります。

于 2008-09-19T23:08:42.893 に答える
3

どういうわけか、多くのスタックを使用しています。考えられる原因としては、スタック上にルーティング テーブルを作成している、スタック上でそれを渡している、または大量の呼び出しを生成している (たとえば、全体を再帰的に処理している) などがあります。

最初の 2 つのケースでは、ヒープ上に作成し、それへのポインターを渡す必要があります。3 番目のケースでは、アルゴリズムを反復形式で書き直す必要があります。

于 2008-09-19T23:27:53.457 に答える
1

多くのオペレーティングシステムは、スタックを使用するにつれて、スタックを動的に拡張します。スタックを超えたメモリアドレスへの書き込みを開始すると、OSはスタックがもう少し大きくなったと見なし、追加のページ(通常、x86では4096Kib-正確に1024インチ)を割り当てます。

問題は、x86(および他のいくつかのアーキテクチャ)では、スタックは下向きに成長しますが、Cアレイは上向きに成長することです。つまり、大きな配列の先頭にアクセスすると、スタックの端から1ページ以上離れたメモリにアクセスすることになります。

配列の最後から始めて配列を0に初期化すると(そうです、forループを作成して実行します)、エラーがなくなる可能性があります。もしそうなら、これは確かに問題です。

スタック割り当てを強制するOSAPI関数、またはコンパイラプラグマ/フラグを見つけることができる場合があります。もちろんmalloc()とfree()を使用する場合を除いて、これを移植可能に行う方法がわかりません。

于 2008-10-29T20:19:08.990 に答える
1

変数を宣言した場所によって異なります。

ローカル変数 (つまり、スタック上で宣言された変数は、最大フレーム サイズによって制限されます) これは、使用しているコンパイラの制限です (通常、コンパイラ フラグで調整できます)。

動的に割り当てられたオブジェクト (つまり、ヒープ上にあるオブジェクト) は、使用可能なメモリの量によって制限されます。これは OS の特性です (スマート OS を使用している場合、技術的には物理メモリを大きくすることができます)。

于 2008-09-20T00:38:48.183 に答える
1

埋め込まれた再帰呼び出しの数が多すぎると、C でスタック オーバーフローが発生する可能性があります。おそらく、関数自体を何度も呼び出していますか?

このエラーは、静的宣言で割り当てられたメモリが多すぎることが原因である可能性もあります。この種の問題を解決するには、malloc() を介して動的割り当てに切り替えることができます。

このプログラムでデバッガを使用できない理由はありますか?

于 2008-09-19T23:14:06.437 に答える
0

暴走した再帰や宇宙のメモリリークなど、特にひどいことをしない限り、スレッド化されていないコンパイル済みCでスタックオーバーフローが発生する可能性はほとんどありません。ただし、シミュレータには、スタックサイズの制限を課すスレッドパッケージが含まれている可能性があります。新しいスレッドを開始すると、そのスレッドのスタックにメモリのチャンクが割り当てられます。おそらく、デフォルトのスタックサイズを確立するパラメータをどこかに設定できます。または、スタックを動的に拡張する方法があるかもしれません。たとえば、pthreadsには、新しいスレッドを開始してサイズを設定する前に呼び出す関数pthread_attr_setstacksize()があります。シミュレーターはpthreadを使用している場合と使用していない場合があります。シミュレータのリファレンスドキュメントを参照してください。

于 2008-09-20T13:38:40.727 に答える