是否有类似Java的
的c ++try {
...
}
catch (Throwable t) {
...
}
我正在尝试调试调用本机Windows函数的Java / jni代码,并且虚拟机不断崩溃。本机代码在单元测试中看起来很好,并且在通过jni调用时似乎只会崩溃。一般的异常捕获机制将非常有用。
答案 0 :(得分:299)
try{
// ...
} catch (...) {
// ...
}
将捕获所有C ++异常,但它应被视为糟糕的设计。您可以使用c ++ 11的新current_exception机制,但如果您无法使用c ++ 11(需要重写的遗留代码系统),那么您没有用于获取消息或名称的命名异常指针。您可能希望为可捕获的各种异常添加单独的catch子句,并且只捕获底部的所有内容以记录意外异常。 E.g:
try{
// ...
} catch (const std::exception& ex) {
// ...
} catch (const std::string& ex) {
// ...
} catch (...) {
// ...
}
答案 1 :(得分:127)
有人应该补充说,在C ++代码中无法捕获“崩溃”。那些不会抛出异常,而是做任何他们喜欢的事情。当你看到程序因为空指针解除引用而崩溃时,它正在做未定义的行为。没有std::null_pointer_exception
。试图捕捉异常对那里没有帮助。
只是有人正在阅读这个帖子,并认为他可以解决程序崩溃的原因。应该使用像gdb这样的调试器。
答案 2 :(得分:56)
try {
// ...
} catch (...) {
// ...
}
请注意...
内的catch
是一个真正的省略号,即。三点。
但是,因为C ++异常不一定是基类Exception
类的子类,所以没有任何方法可以实际看到使用此构造时抛出的异常变量。
答案 3 :(得分:49)
如果您需要(在从第三方库中捕获未知时可能很有用),您可以从catch(...)
内对异常类型进行反向工程:G / C
#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;
}
答案 4 :(得分:34)
不可能(在C ++中)以可移植的方式捕获所有异常。这是因为某些异常在C ++上下文中不是异常。这包括除零错误等等。当这些错误发生时,有可能破解并因此获得抛出异常的能力,但这样做并不容易,并且当然不容易以可移植的方式正确。
如果要捕获所有STL异常,可以执行
try { ... } catch( const std::exception &e) { ... }
这将允许您使用e.what()
,它将返回const char*
,它可以告诉您有关异常本身的更多信息。这是一个类似于Java构造的构造,你问的最多。
如果有人愚蠢地抛出不从std::exception
继承的异常,这对你没有帮助。
答案 5 :(得分:21)
简而言之,请使用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(...)
的正确方法。
答案 6 :(得分:18)
可以通过写:
来做到这一点try
{
//.......
}
catch(...) // <<- catch all
{
//.......
}
但是这里存在一个非常明显的风险:您无法找到try
块中引发的确切错误类型,因此当您确定时,请使用此类catch
无论什么类型的异常,程序必须以catch
块中定义的方式保持。
答案 7 :(得分:17)
您可以使用
catch(...)
但这非常危险。约翰罗宾斯在他的书Debugging Windows中讲述了一个关于一个非常令人讨厌的错误的战争故事,这个错误被一个catch(...)命令掩盖了。捕获特定异常会更好。抓住你认为你的try块可能合理抛出的任何东西,但如果发生了意想不到的事情,让代码抛出更高的异常。
答案 8 :(得分:12)
我在这里提一下:Java
try
{
...
}
catch (Exception e)
{
...
}
可能无法捕获所有异常!事实上,我之前已经发生过这样的事情,而且这是令人厌恶的;异常来自Throwable。从字面上看,要抓住一切,你不要想抓住例外;你想抓住Throwable。
我知道这听起来很挑剔,但是当你花了几天的时间试图找出“未捕获的异常”来自代码的地方时,其中包含了一个try ... catch(异常e)“块来自,它坚持你。
答案 9 :(得分:7)
好吧,如果您想捕获所有例外来创建一个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
默认情况下,这会在当前目录(crashdump.dmp)中创建一个minidump
答案 10 :(得分:4)
通用异常捕获机制 会证明非常有用。
疑。你已经知道你的代码坏了,因为它崩溃了。吃异常可能会掩盖这一点,但这可能只会导致更糟糕,更微妙的错误。
你真正想要的是一个调试器......
答案 11 :(得分:2)
您是否可以从控制台窗口运行使用JNI的Java应用程序(从java命令行启动它),以查看是否有任何关于在JVM崩溃之前可能检测到的内容的报告。直接作为Java窗口应用程序运行时,如果从控制台窗口运行,则可能会丢失显示的消息。
其次,您可以存根JNI DLL实现,以显示您的DLL中的方法是从JNI输入的,您是否正确返回等等?
如果问题是错误地使用了C ++代码中的一个JNI接口方法,您是否已经验证了一些简单的JNI示例是否可以编译并使用您的设置?我正在考虑使用JNI接口方法将参数转换为本机C ++格式并将函数结果转换为Java类型。保留这些数据以确保数据转换正常工作并且在类似COM的JNI接口调用中不会出现问题是非常有用的。
还有其他事情需要检查,但如果不了解更多有关您的本机Java方法以及它们正在尝试执行的JNI实现的内容,则很难建议。目前尚不清楚从C ++代码级别捕获异常与您的问题有关。 (您可以使用JNI接口将异常重新抛出为Java,但不清楚您提供的内容是否有帮助。)
答案 12 :(得分:2)
注意
try{
// ...
} catch (...) {
// ...
}
仅捕获语言级别的异常,不会捕获其他低级别的异常/错误,例如Access Violation
和Segmentation Fault
。
答案 13 :(得分:1)
关于无法正确调试使用JNI的程序的真正问题(或者在调试器下运行时不会出现错误):
在这种情况下,通常有助于在JNI调用周围添加Java包装器(即所有本机方法都是私有的,并且类中的公共方法调用它们),这些方法执行一些基本的健全性检查(检查所有“对象”是否已释放,以及释放后不使用“对象”或同步(只是将所有方法从一个DLL同步到单个对象实例)。让java包装器方法记录错误并抛出异常。
这通常会比试图调试大规模并行Java更容易找到真正的错误(令人惊讶地主要是在Java代码中不遵守被调用函数的语义导致一些讨厌的双重释放或类似)本机调试器中的程序......
如果您知道原因,请将代码保留在包装器方法中以避免它。最好让你的包装器方法抛出异常而不是你的JNI代码崩溃VM ...
答案 14 :(得分:0)
这真的取决于编译环境。 gcc没有抓住这些。 Visual Studio和我用过的最后一个Borland。
因此,关于崩溃的结论是它取决于您的开发环境的质量。
C ++ 规范说catch(...)必须捕获任何异常,但并非在所有情况下都是如此。
至少从我的尝试开始。
答案 15 :(得分:0)
如果您正在寻找特定于 Windows 的解决方案,那么有结构化异常处理: https://docs.microsoft.com/en-us/cpp/cpp/try-except-statement
代码如下
__try
{
// code here may throw or make access violation
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
// after exception code here, e.g. log the error
}
它不仅会捕获 C++ 异常,还会捕获访问冲突或其他系统异常。