c++捕获所有异常

c++中有类似Java的吗

try {
...
}
catch (Throwable t) {
...
}

我试图调试Java/jni代码调用本机windows函数和虚拟机不断崩溃。本机代码在单元测试中表现良好,只有在通过jni调用时才会崩溃。一个通用的异常捕获机制将被证明是非常有用的。

467201 次浏览
try {
// ...
} catch (...) {
// ...
}

注意,catch中的...是一个真正的省略号,即。三个点。

然而,由于c++异常不一定是基Exception类的子类,因此在使用此构造时无法实际看到抛出的异常变量。

你可以使用

catch(...)

但这是非常危险的。在他的书调试窗口中,约翰·罗宾斯讲述了一个战争故事,一个非常讨厌的虫子被一个捕捉(…)命令掩盖了。您最好捕获特定的异常。捕获您认为try块可能合理抛出的任何异常,但如果确实发生意外,则让代码抛出更高的异常。

try{
// ...
} catch (...) {
// ...
}

将捕获所有c++异常,但它应该被认为是糟糕的设计。你可以使用c++11新的current_exception机制,但是如果你没有能力使用c++11(遗留代码系统需要重写),那么你就没有命名异常指针来获取消息或名称。您可能希望为可以捕获的各种异常添加单独的catch子句,并且只捕获底部的所有内容以记录意外异常。例如:

try{
// ...
} catch (const std::exception& ex) {
// ...
} catch (const std::string& ex) {
// ...
} catch (...) {
// ...
}

让我在这里提一下:Java

try
{
...
}
catch (Exception e)
{
...
}

可能无法捕获所有异常!其实我以前也遇到过这种事,很让人抓狂;Exception派生自Throwable。因此,从字面上看,要捕获所有东西,你不希望捕获异常;你想抓住Throwable。

我知道这听起来很挑剔,但是当你花了好几天时间试图弄清楚“未捕获的异常”来自于被try包围的代码时……catch (Exception e)" block来自哪里,它会一直跟着你。

一个通用的异常捕获机制

表示怀疑。你已经知道你的代码坏了,因为它崩溃了。进食异常可能会掩盖这一点,但这可能只会导致更糟糕、更微妙的错误。

你真正需要的是一个调试器……

有人应该补充说,在c++代码中无法捕捉“崩溃”。它们不会抛出异常,而是做任何它们喜欢做的事情。当你看到一个程序因为空指针的解引用而崩溃时,它正在做未定义的行为。没有std::null_pointer_exception。试图捕捉异常在那里没有帮助。

只是为了以防万一,有人正在阅读这篇文章,并认为他可以得到程序崩溃的原因。应该使用像gdb这样的调试器。

  1. 您是否可以从控制台窗口(从Java命令行启动它)运行使用jni的Java应用程序,以查看是否有关于JVM崩溃之前可能检测到的内容的报告。当直接作为Java窗口应用程序运行时,您可能会错过从控制台窗口运行时会出现的消息。

  2. 其次,你能否存根你的JNI DLL实现,以显示你的DLL中的方法是从JNI输入的,你是正确返回的,等等?

  3. 以防问题是由于错误地使用了c++代码中的某个JNI接口方法,您是否验证了一些简单的JNI示例是否可以编译并与您的设置一起工作?我特别考虑使用jni接口方法将参数转换为原生c++格式,并将函数结果转换为Java类型。存根是很有用的,它可以确保数据转换正常工作,并且在对JNI接口的类似com的调用中不会出现混乱。

  4. 还有其他需要检查的东西,但是如果不进一步了解本机Java方法是什么以及它们的JNI实现试图做什么,就很难提出任何建议。从c++代码级别捕获异常是否与您的问题相关尚不清楚。(您可以使用JNI接口将异常作为Java异常重新抛出,但从您提供的内容来看,并不清楚这样做是否有帮助。)

(在c++中)以可移植的方式捕获所有异常是不可能的。这是因为在c++上下文中,有些异常并不是异常。这包括除以零误差等。可以通过破解来获得在这些错误发生时抛出异常的能力,但这并不容易做到,当然也不容易以一种可移植的方式得到正确的处理。

如果你想捕获所有的STL异常,你可以这样做

try { ... } catch( const std::exception &e) { ... }

这将允许你使用e.what(),它将返回一个const char*,它可以告诉你关于异常本身的更多信息。这是与Java构造最相似的构造。

如果有人愚蠢到抛出一个不继承std::exception的异常,这将对你没有帮助。

对于无法正确调试使用JNI的程序的真正问题(或者在调试器下运行时不出现错误):

在这种情况下,在JNI调用(即所有本机方法都是私有的,类中的公共方法调用它们)周围添加Java包装器通常会有所帮助,这些包装器会做一些基本的完整性检查(检查所有“对象”都被释放,释放后“对象”没有被使用)或同步(将所有方法从一个DLL同步到单个对象实例)。让java包装器方法记录错误并抛出异常。

这通常有助于发现真正的错误(令人惊讶的是,这些错误主要出现在Java代码中,不遵守被调用函数的语义,导致一些讨厌的double-free或类似的情况),比尝试在本地调试器中调试大型并行Java程序更容易……

如果您知道原因,请将代码保存在可以避免该原因的包装器方法中。最好让你的包装器方法抛出异常,而不是你的JNI代码崩溃VM…

可以这样写:

try
{
//.......
}
catch(...) // <<- catch all
{
//.......
}

但是这里有一个非常不明显的风险:你无法找到在try块中抛出的错误的确切类型,所以当你确定无论异常类型是什么,程序必须以catch块中定义的方式存在时,使用这种catch

简而言之,使用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(...)的正确方法。

这是你如何从catch(...)中反向工程异常类型,如果你需要(可能有用时,从第三方库捕获未知)使用GCC:

#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;
}

如果你有能力使用提高,你可以让你的catch部分更简单(在外部),并且可能是跨平台的

catch (...)
{
std::clog << boost::current_exception_diagnostic_information() << std::endl;
}

嗯,如果你想捕获所有异常来创建一个小转储,例如…

有人做了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

< br >

默认情况下,这会在当前目录(crashdump.dmp)中创建一个迷你转储。

这取决于编译器环境。 GCC不捕获这些。 Visual Studio和我使用的最后一个Borland

因此,关于崩溃的结论是,它取决于开发环境的质量。

< p > C + + 规范说catch(…)必须捕获任何异常,但它不是在所有情况下都捕获

至少我是这么想的。

请注意

try{
// ...
} catch (...) {
// ...
}

仅捕获语言级异常,其他低级异常/错误如Access ViolationSegmentation Fault不会被捕获。

如果你正在寻找windows解决方案,那么有结构化异常处理: https://learn.microsoft.com/en-us/cpp/cpp/try-except-statement < / p >

代码如下所示

__try
{
// code here may throw or make access violation
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
// after exception code here, e.g. log the error
}

它不仅可以捕获c++异常,还可以捕获访问违规或其他系统异常。