100 X 100アレイでDFSを実行したい。(たとえば、配列の要素はグラフのノードを表します)したがって、最悪の場合を想定すると、再帰関数呼び出しの深さは最大10000になり、各呼び出しは最大で20バイトを使用します。それで、スタックオーバーフローの可能性があるのは実行可能な手段ですか?
C / C ++のスタックの最大サイズはいくつですか?
両方のgccを指定してください
1)Windows上のcygwin
2)Unix
一般的な制限は何ですか?
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のデフォルトスタックサイズのです。
再帰なしの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がコミットされますが、プログラムをリンクするときに変更できます。それを行うには、--stack
オプションを使用しますld
。
私は仕事でスタックを使い果たしました、それはデータベースであり、いくつかのスレッドを実行していました。基本的に、前の開発者がスタックに大きな配列をスローし、スタックはとにかく低かったです。ソフトウェアは、Microsoft Visual Studio 2015を使用してコンパイルされました。
スレッドはスタックを使い果たしましたが、黙って失敗して続行しましたが、スタック上のデータの内容にアクセスするようになったときにのみ、スタックがオーバーフローしました。
私ができる最善のアドバイスは、スタックで配列を宣言しないことです。特に複雑なアプリケーションやスレッドでは、代わりにヒープを使用してください。それがそこにあります;)
また、スタックの宣言時にすぐに失敗するのではなく、アクセス時にのみ失敗する可能性があることにも注意してください。私の推測では、コンパイラーはウィンドウの下でスタックを「楽観的に」宣言します。つまり、スタックが宣言されていて、それを使用するようになるまで十分なサイズであると想定して、そこにスタックがないことがわかります。
オペレーティングシステムが異なれば、スタック宣言ポリシーも異なります。これらのポリシーについてご存知の場合は、コメントを残してください。