100 X 100アレイでDFSを実行したい。 (配列の要素はグラフノードを表します)したがって、最悪の場合、再帰関数呼び出しの深さは最大10000になり、呼び出しごとに最大20バイトかかることがあります。だから、それは実行可能な手段であり、スタックオーバーフローの可能性がありますか?
C/C++のスタックの最大サイズは?
両方のgccを指定してください
1)Windows上のcygwin
2)Unix
一般的な制限は何ですか?
Visual Studioでは、デフォルトのスタックサイズは1 MBであると考えられます。したがって、再帰深度が10,000の場合、各スタックフレームは最大で最大100バイトであり、DFSアルゴリズムに十分です。
Visual Studioを含むほとんどのコンパイラでは、スタックサイズを指定できます。一部の(すべて?)Linuxフレーバーでは、スタックサイズは実行可能ファイルの一部ではなく、OSの環境変数です。その後、ulimit -s
を使用してスタックサイズを確認し、たとえばulimit -s 16384
を使用して新しい値に設定できます。
これは、gccのデフォルトのスタックサイズを使用した link です。
再帰なしのDFS:
std::stack<Node> dfs;
dfs.Push(start);
do {
Node top = dfs.top();
if (top is what we are looking for) {
break;
}
dfs.pop();
for (outgoing nodes from top) {
dfs.Push(outgoing node);
}
} while (!dfs.empty())
多くの場合、スレッドのスタックは小さくなります。リンク時にデフォルトを変更することも、実行時に変更することもできます。参考のために、いくつかのデフォルトは次のとおりです。
プラットフォーム依存、ツールチェーン依存、ulimit依存、パラメータ依存...これはまったく指定されておらず、それに影響を与えることができる静的および動的プロパティが多数あります。
はい、スタックオーバーフローの可能性があります。 CおよびC++標準では、スタックの深さなどは規定されていません。これらは一般に環境問題です。
適切な開発環境やオペレーティングシステムのほとんどでは、リンク時またはロード時にプロセスのスタックサイズを調整できます。
よりターゲットを絞った支援を得るには、使用しているOSと開発環境を指定する必要があります。
たとえば、Ubuntu Karmic Koalaでは、gccのデフォルトは2M予約済みで4Kコミットですが、プログラムをリンクするときにこれを変更できます。これを行うには、ld
の--stack
オプションを使用します。
私はちょうど仕事でスタックを使い果たしました。それはデータベースであり、いくつかのスレッドを実行していました。基本的に、前の開発者はスタックに大きな配列を投げていました。ソフトウェアは、Microsoft Visual Studio 2015を使用してコンパイルされました。
スレッドがスタックを使い果たしても、静かに失敗して続行しましたが、スタック上のデータのコンテンツにアクセスするようになったときにのみスタックがオーバーフローしました。
私ができる最善のアドバイスは、スタック上で配列を宣言しないことです。特に複雑なアプリケーション、特にスレッドでは、代わりにヒープを使用します。それがそこにあるものです;)
また、スタックの宣言時にすぐに失敗するのではなく、アクセス時にのみ失敗する可能性があることに注意してください。私の推測では、コンパイラはウィンドウの下でスタックを「楽観的に」宣言します。つまり、スタックが宣言され、使用するまで十分なサイズであると仮定し、スタックが存在しないことがわかります。
オペレーティングシステムごとにスタック宣言ポリシーが異なる場合があります。これらのポリシーについてご存知の場合は、コメントを残してください。
長方形の配列で深さ優先検索を行うことで何を意味するのかわかりませんが、何をしているのか知っていると思います。
スタック制限が問題である場合、再帰的ソリューションを、ヒープから割り当てられたスタックに中間値をプッシュする反復ソリューションに変換できるはずです。