我知道我可以使用 Thread.getAllStackTraces() 获取堆栈跟踪(它返回 Map,但 clear 不起作用)。当我运行递归方法时,由于堆栈跟踪太大,我会得到异常,有没有办法清除它?
3 回答
导致问题的不是堆栈跟踪,而是堆栈本身。每次调用方法时,都会将信息放入堆栈,以便您返回调用方法。如果你递归的足够多,最终你会填满堆栈上的所有空间(由最大大小限制)并且你的程序会停止。堆栈跟踪只是向您显示您的调用历史记录。您可能正在进行无限递归,需要在程序失败之前找到一种方法来阻止它。要么你的算法有错误,要么你需要在你可用的内存范围内找到一种不同的方法来解决它。
如果由于递归失控而导致堆栈溢出,那么您就不走运了。堆栈的内容需要从函数调用返回,没有办法明智地“清理它”。问题不在于 getAllStackTraces() 返回的 Map,而在于堆栈的实际内容。
您需要重组您的代码,使其不会递归到如此深的层次。
或者,您可以调查是否有可能增加堆栈的大小,但要求非标准堆栈大小通常是有问题的实现的标志。
首先检查您的程序在其代码中没有导致无限递归导致堆栈溢出的错误。
如果不是这种情况,您可以尝试为您的程序分配更多的堆栈空间。在 Linux 下,您可以使用ulimit
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
}
}
它做你想做的事,但它并不是一种很好的编程风格。请注意,您需要想出一种方法来知道何时清除堆栈。这可能非常困难,因为您不知道还剩下多少堆栈空间,或者调用函数是否会溢出堆栈!