什么是什么,是StackOverflowError什么导致它,我应该如何处理它们?
stack-overflow memory-leaks exception-handling out-of-memory
看看以下两种方法:
public static void foo() {
try {
foo();
} finally {
foo();
}
}
public static void bar() {
bar();
}
Run Code Online (Sandbox Code Playgroud)
运行bar()清楚导致a StackOverflowError,但运行foo()没有(程序似乎只是无限期运行).这是为什么?
我到处寻找,找不到可靠的答案.根据文档,Java 在以下情况下抛出java.lang.StackOverflowError错误:
在发生堆栈溢出时抛出,因为应用程序过于严重.
但这提出了两个问题:
详细说明第二个问题:
当Java抛出StackOverflowError时,你能安全地假设堆栈没有写入堆中吗?如果你在一个抛出堆栈溢出的函数的try/catch中缩小堆栈或堆的大小,你能继续工作吗?这记录在哪里?
答案我不是在寻找:
我有以下代码失败,出现以下错误:
RuntimeError:超出最大递归深度
我试图重写它以允许尾递归优化(TCO).我相信如果发生TCO,这段代码应该是成功的.
def trisum(n, csum):
if n == 0:
return csum
else:
return trisum(n - 1, csum + n)
print(trisum(1000, 0))
Run Code Online (Sandbox Code Playgroud)
我是否应该断定Python不执行任何类型的TCO,或者我只是需要以不同的方式定义它?
这是我的示例代码:
#include <iostream>
#include <string>
using namespace std;
class MyClass
{
string figName;
public:
MyClass(const string& s)
{
figName = s;
}
const string& getName() const
{
return figName;
}
};
ostream& operator<<(ostream& ausgabe, const MyClass& f)
{
ausgabe << f.getName();
return ausgabe;
}
int main()
{
MyClass f1("Hello");
cout << f1;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果我注释掉,#include <string>我没有得到任何编译器错误,我想因为它包含在内#include <iostream>.如果我在Microsoft VS中"右键单击 - >转到定义",它们都指向xstring文件中的同一行:
typedef basic_string<char, char_traits<char>, allocator<char> >
string;
Run Code Online (Sandbox Code Playgroud)
但是当我运行我的程序时,我收到一个异常错误:
OperatorString.exe中的0x77846B6E(ntdll.dll):0xC00000FD:堆栈溢出(参数:0x00000001,0x01202FC4)
知道为什么我在评论时出现运行时错误#include <string> …
我问这个问题是为了了解如何在JVM中增加运行时调用堆栈的大小.我已经得到了答案,我还得到了许多有用的答案和评论,这些答案和评论与Java如何处理需要大型运行时堆栈的情况有关.我已经用答案摘要扩展了我的问题.
最初我想增加JVM堆栈大小,所以程序就像没有运行的程序一样StackOverflowError.
public class TT {
public static long fact(int n) {
return n < 2 ? 1 : n * fact(n - 1);
}
public static void main(String[] args) {
System.out.println(fact(1 << 15));
}
}
Run Code Online (Sandbox Code Playgroud)
相应的配置设置是java -Xss...具有足够大值的命令行标志.对于TT上面的程序,它与OpenJDK的JVM一样:
$ javac TT.java
$ java -Xss4m TT
Run Code Online (Sandbox Code Playgroud)
其中一个答案还指出,这些-X...标志是依赖于实现的.我在用
java version "1.6.0_18"
OpenJDK Runtime Environment (IcedTea6 1.8.1) (6b18-1.8.1-0ubuntu1~8.04.3)
OpenJDK 64-Bit Server VM (build 16.0-b13, mixed mode)
Run Code Online (Sandbox Code Playgroud)
也可以仅为一个线程指定一个大堆栈(参见其中一个答案如何).建议使用此方法java -Xss...以避免为不需要它的线程浪费内存.
我很好奇上面的程序需要多大的堆栈,所以我运行它n增加了:
fact(1 …我想知道当你试图捕获StackOverflowError时会发生什么,并提出以下方法:
class RandomNumberGenerator {
static int cnt = 0;
public static void main(String[] args) {
try {
main(args);
} catch (StackOverflowError ignore) {
System.out.println(cnt++);
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在我的问题:
为什么这个方法打印'4'?
我想也许是因为System.out.println()在调用堆栈上需要3个段,但我不知道3号来自哪里.当你查看源代码(和字节码)时System.out.println(),它通常会导致比3更多的方法调用(因此调用堆栈上的3个段是不够的).如果是因为优化热点VM应用(方法内联),我想知道其他VM上的结果是否会有所不同.
编辑:
由于输出似乎是高度JVM特定的,我使用
Java(TM)SE运行时环境(构建1.6.0_41-b02)
Java HotSpot(TM)64位服务器VM(构建20.14-b01,混合模式)得到结果4
解释为什么我认为这个问题与理解Java堆栈不同:
我的问题不是为什么有一个cnt> 0(显然是因为System.out.println()需要堆栈大小并StackOverflowError在某些东西被打印之前抛出另一个),但为什么它具有特定值4,分别为0,3,8,55或其他的其他东西系统.
我得到一个递归调用一个抛出堆栈溢出异常的方法.第一个调用被try catch块包围,但没有捕获异常.
堆栈溢出异常是否以特殊方式运行?我可以正确捕获/处理异常吗?
注意:如果相关:
主线程中没有抛出异常
代码抛出异常的对象由Assembly.LoadFrom(...)手动加载.CreateInstance(...)
我在chrome上收到错误"未捕获RangeError:超出最大调用堆栈大小".这是我的jQuery函数
$('td').click(function () {
if ($(this).context.id != null && $(this).context.id != '') {
foo($('#docId').val(), $(this).attr('id'));
}
return false;
});
Run Code Online (Sandbox Code Playgroud)
请注意,页面中有数万个单元格.但是,我通常将堆栈溢出与递归相关联,在这种情况下,据我所知,没有.
创建这样的lambda会自动在堆栈上生成一堆东西吗?有什么办法吗?
目前我唯一的解决方法是在呈现HTML时在每个单元格上显式生成onclick事件,这使得HTML更大.
我很惊讶即使StackOverflowError在Java发生之后仍然可以继续执行.
我知道这StackOverflowError是类Error的子类.类Error被称为"Throwable的一个子类,表示一个合理的应用程序不应该试图捕获的严重问题".
这听起来更像是一个推荐而不是一个规则,主张捕获像StackOverflowError这样的错误实际上是允许的,这取决于程序员不这样做的合理性.看,我测试了这段代码,它正常终止.
public class Test
{
public static void main(String[] args)
{
try {
foo();
} catch (StackOverflowError e) {
bar();
}
System.out.println("normal termination");
}
private static void foo() {
System.out.println("foo");
foo();
}
private static void bar() {
System.out.println("bar");
}
}
Run Code Online (Sandbox Code Playgroud)
怎么会这样?我想当抛出StackOverflowError时,堆栈应该是如此完整,以至于没有空间调用另一个函数.错误处理块是在不同的堆栈中运行,还是在这里发生了什么?
stack-overflow ×10
java ×5
jvm ×2
recursion ×2
stack ×2
c# ×1
c++ ×1
explicit ×1
javascript ×1
jquery ×1
memory-leaks ×1
python ×1
string ×1
try-catch ×1
try-finally ×1
webkit ×1