是否有Java的c ++等价物
try {
...
}
catch (Throwable t) {
...
}
我正在尝试调试调用本机Windows函数的Java / jni代码,并且虚拟机不断崩溃。本机代码在单元测试中看起来很好,并且在通过jni调用时似乎只会崩溃。一般的异常捕获机制将证明是非常有用的。
try{
// ...
} catch (...) {
// ...
}
将捕获所有C ++异常,但它应被视为糟糕的设计。您可以使用c ++ 11的新current_exception机制,但如果您无法使用c ++ 11(需要重写的遗留代码系统),那么您没有用于获取消息或名称的命名异常指针。您可能希望为可捕获的各种异常添加单独的catch子句,并且只捕获底部的所有内容以记录意外异常。例如。:
try{
// ...
} catch (const std::exception& ex) {
// ...
} catch (const std::string& ex) {
// ...
} catch (...) {
// ...
}
好吧,如果你想捕获所有异常来创建一个minidump例如......
有人在Windows上完成了这项工作。
请参阅http://www.codeproject.com/Articles/207464/Exception-Handling-in-Visual-Cplusplus在文章中,他解释了他如何发现如何捕获所有类型的异常并提供可行的代码。
以下是您可以捕获的列表:
SEH exception
terminate
unexpected
pure virtual method call
invalid parameter
new operator fault
SIGABR
SIGFPE
SIGILL
SIGINT
SIGSEGV
SIGTERM
Raised exception
C++ typed exception
用法:CCrashHandler ch; ch.SetProcessExceptionHandlers(); //为一个线程执行此操作ch.SetThreadExceptionHandlers(); //为每个thred
默认情况下,这会在当前目录中创建一个minidump(crashdump.dmp)
一般的异常捕获机制将证明是非常有用的。
疑。你已经知道你的代码坏了,因为它崩溃了。吃异常可能会掩盖这一点,但这可能只会导致更糟糕,更微妙的错误。
你真正想要的是一个调试器......
对于无法正确调试使用JNI的程序的真正问题(或者在调试器下运行时不会出现错误):
在这种情况下,通常有助于在JNI调用周围添加Java包装器(即所有本机方法都是私有的,并且类中的公共方法调用它们)进行一些基本的健全性检查(检查所有“对象”是否被释放和“对象”)在释放之后不使用)或同步(只是将所有方法从一个DLL同步到单个对象实例)。让java包装器方法记录错误并抛出异常。
这通常有助于找到真正的错误(这令人惊讶地主要在Java代码中,它不遵守被调用函数的语义导致一些讨厌的双重释放或类似)比试图调试大规模并行Java程序更容易本机调试器......
如果您知道原因,请将代码保存在您的包装器方法中以避免它。最好让你的包装器方法抛出异常而不是你的JNI代码崩溃VM ...
那真的取决于编译环境。 gcc没有抓住这些。 Visual Studio和我用过的最后一个Borland。
因此,关于崩溃的结论是它取决于您的开发环境的质量。
C ++规范说catch(...)必须捕获任何异常,但并非在所有情况下都如此。
至少从我的尝试。
有人应该补充说,在C ++代码中无法捕获“崩溃”。那些不会抛出异常,而是做任何他们喜欢的事情。当你看到程序因为空指针解除引用而崩溃时,它正在做未定义的行为。没有std::null_pointer_exception
。试图捕捉异常对那里没有帮助。
只是因为有人正在阅读这个帖子,并认为他可以得到程序崩溃的原因。应该使用像gdb这样的调试器。
try {
// ...
} catch (...) {
// ...
}
请注意,...
中的catch
是一个真正的省略号,即。三个点。
但是,因为C ++异常不一定是基本Exception
类的子类,所以没有任何方法可以实际查看使用此构造时引发的异常变量。
如果您需要(在从第三方库中捕获未知时可能很有用),您可以使用GCC从catch(...)
中对异常类型进行反向工程:
#include <iostream>
#include <exception>
#include <typeinfo>
#include <stdexcept>
int main()
{
try {
throw ...; // throw something
}
catch(...)
{
std::exception_ptr p = std::current_exception();
std::clog <<(p ? p.__cxa_exception_type()->name() : "null") << std::endl;
}
return 1;
}
如果你能负担得起使用Boost,你可以让你的捕获部分更简单(在外面)和潜在的跨平台
catch (...)
{
std::clog << boost::current_exception_diagnostic_information() << std::endl;
}
不可能(在C ++中)以可移植的方式捕获所有异常。这是因为某些异常在C ++上下文中不是异常。这包括除零错误等等。当这些错误发生时,有可能破解并因此获得抛出异常的能力,但这并不容易,并且当然不容易以可移植的方式获得正确。
如果你想捕获所有STL异常,你可以这样做
try { ... } catch( const std::exception &e) { ... }
这将允许你使用e.what()
,它将返回一个const char*
,它可以告诉你更多关于异常本身。这是一个类似于Java构造的构造,你问的最多。
如果有人愚蠢到抛出不从std::exception
继承的异常,这对你没有帮助。
简而言之,使用catch(...)
。但请注意,catch(...)
基本上应与throw;
一起使用:
try{
foo = new Foo;
bar = new Bar;
}
catch(...) // will catch all possible errors thrown.
{
delete foo;
delete bar;
throw; // throw the same error again to be handled somewhere else
}
这是使用catch(...)
的正确方法。
可以这样写:
try
{
//.......
}
catch(...) // <<- catch all
{
//.......
}
但是这里存在一个非常明显的风险:你找不到try
块中抛出的确切类型的错误,所以当你确定无论什么类型的异常是什么时,使用这种catch
,程序必须坚持在catch
区块中定义的方式。
您可以使用
catch(...)
但那非常危险。在他的书Debugging Windows中,约翰罗宾斯讲述了一个关于一个非常讨厌的错误的战争故事,这个错误被一个catch(...)命令所掩盖。捕获特定异常会更好。抓住你认为你的try块可能合理抛出的任何东西,但是如果出现意外的事情,让代码抛出更高的异常。
我在这里只提一下:Java
try
{
...
}
catch (Exception e)
{
...
}
可能无法捕获所有异常!事实上,我之前已经发生过这样的事情,而且这是令人厌恶的;异常来自Throwable。从字面上看,要抓住一切,你不要想抓住例外;你想抓住Throwable。
我知道这听起来很挑剔,但是当你花了几天的时间试图找出“未被捕获的异常”来自代码的地方时,其中包含了一个尝试...捕获(例外e)“块来自,它坚持您。