0

Thread.getAllStackTraces()を使用してスタックトレースを取得できることを知っています(Mapを返しますが、clearは機能しません)。再帰メソッドを実行すると、スタックトレースが大きすぎるために例外が発生する可能性がありますが、それをクリアする方法はありますか?

4

3 に答える 3

4

問題を引き起こしているのはスタックトレースではなく、スタック自体です。メソッドを呼び出すたびに、呼び出し元のメソッドに戻ることができる情報がスタックに置かれます。十分に再帰すると、最終的にスタック上のすべてのスペース(最大サイズによって制限されます)がいっぱいになり、プログラムが停止します。スタックトレースは、単に通話の履歴を示します。おそらく無限の再帰が進行中であり、プログラムが失敗する前にそれを停止する方法を見つける必要があります。アルゴリズムにエラーがあるか、使用可能なメモリの範囲内で別の方法でそれを解決する方法を見つける必要があります。

于 2008-10-16T12:24:03.300 に答える
1

再帰が制御不能になったためにスタックオーバーフローが発生した場合は、運が悪いことになります。スタックの内容は関数呼び出しから戻るために必要であり、賢明に「クリーンアップ」する方法はありません。問題は、getAllStackTraces()によって返されるマップではなく、スタックの実際の内容です。

コードがそれほど深いレベルに再発しないように、コードを再構築する必要があります。

または、スタックのサイズを増やすことが可能かどうかを調査することもできますが、非標準のスタックサイズが必要な場合は、通常、実装に問題があることを示しています。

于 2008-10-16T12:24:07.573 に答える
-1

まず、プログラムにコードにバグがなく、スタックオーバーフローにつながる無限再帰が発生していないことを確認します。

そうでない場合は、プログラムにより多くのスタックスペースを割り当てようとすることができます。ulimitLinuxでは、次のようなbashコマンドを使用して実行できます。

ulimit -s 8000

あるいは

ulimit -s unlimited

本当にスタックを巻き戻す必要がある場合は、Cでsetjmp / longjumpを使用するか、次のような例外または継続を使用できます。

struct ClearStack {} ;

void myLongComputationWhichCausesStackOverflow() {
  // do something
  if (needsToClearTheStack)
    throw ClearStack() ;
  // do something else
}

int main(int ac, char *av[]) {
  try {
    mylongcomputation() ;
    // continuation of program
    // no stack clearing occurred
  }
  catch(const ClearStack & cs) {
    // the stack was cleared and do something appropriately
  }
}

それはあなたが望むことをしますが、それは本当に良いプログラミングスタイルではありません。スタックをクリアするタイミングを知る方法を考え出す必要があることに注意してください。スタックスペースがどれだけ残っているかわからないため、または関数を呼び出すとスタックがオーバーフローするかどうかがわからないため、これは非常に難しい場合があります。

于 2008-10-16T13:53:15.600 に答える