C ++捕获所有exception
有没有Java的C ++等价物
try { ... } catch (Throwable t) { ... }
我正在尝试debugging调用本机窗口函数的Java / jni代码,并且虚拟机不断崩溃。 本机代码在unit testing中显示正常,只有在通过jni调用时才会崩溃。 通用的exception捕获机制将非常有用。
try{ // ... } catch (...) { // ... }
将捕获所有的C ++exception,但应该被认为是不好的devise。 你可以使用c ++ 11的新的current_exception机制,但是如果你没有能力使用c ++ 11(需要重写的遗留代码系统),那么你没有命名的exception指针来获取消息或者名字。 您可能需要为可以捕获的各种exception添加单独的catch子句,并只捕获底部的所有内容以logging意外的exception。 例如:
try{ // ... } catch (const std::exception& ex) { // ... } catch (const std::string& ex) { // ... } catch (...) { // ... }
有人应该补充说,不能捕捉C ++代码中的“崩溃”。 那些不会抛出exception,而是做任何他们喜欢的事情。 当你看到一个程序崩溃,因为说一个空指针解引用,这是做undefined behavior
。 没有std::null_pointer_exception
。 试图捕捉exception并不会对此有所帮助。
只是为了这个案例有人正在阅读这个线程,并认为他可以得到程序崩溃的原因。 应该使用类似于gdb的debugging器。
try { // ... } catch (...) { // ... }
请注意,在catch
内部是一个真正的省略号,即。 三个点。
但是,由于C ++exception不一定是基类Exception
类的子类,所以在使用此构造时,实际上没有任何方法可以看到引发的exceptionvariables。
如果您需要(如果从第三方库中捕获未知数据时可能会有帮助),可以使用GCC从catch(...)
反向deviseexceptiontypes:
#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部分变得更简单(在外部)并且可能跨平台
catch (...) { std::clog << boost::current_exception_diagnostic_information() << std::endl; }
(用C ++)不可能以便携的方式捕获所有exception。 这是因为一些exception在C ++上下文中不是例外。 这包括诸如由零错误等分开的事情。 当发生这些错误时,有可能破解并且能够抛出exception,但是做起来并不容易,当然也不容易以便携的方式获得。
如果你想捕获所有的STLexception,你可以这样做
try { ... } catch( const std::exception &e) { ... }
这将允许你使用e.what()
,它将返回一个const char*
,它可以告诉你更多关于exception本身的信息。 这是最类似于Java构造的构造。
如果有人足够愚蠢,抛出一个不能从std::exception
inheritance的exception,这将无济于事。
您可以使用
catch(...)
但这是非常危险的。 在他的“ debuggingWindows”一书中,John Robbins讲述了一个被catch(…)命令掩盖的非常讨厌的bug的战争故事。 捕捉特定的例外情况要好得多。 抓住任何你认为你的try块可能合理抛出,但让代码抛出一个exception更高,如果真的意外的事情发生。
可以这样写:
try { //....... } catch(...) // <<- catch all { //....... }
但是这里有一个非常不明显的风险:你不能find在try
块中抛出的错误的确切types,所以当你确信不pipe什么types的exception,程序都使用这种catch
必须坚持在catch
块中定义的方式。
让我在这里提到这个:Java
try { ... } catch (Exception e) { ... }
可能无法捕捉所有的例外! 实际上我曾经发生过这种事情,这是一种引人注目的事情。 exception来自Throwable。 所以从字面上看,要抓住一切,你不想抓住例外; 你想抓Throwable。
我知道这听起来很挑剔,但是当你花了几天的时间试图找出“未捕获的exception”来自try … catch(Exception e)所包围的代码的块来自何处时,它坚持您。
总之,使用catch(...)
。 但是请注意, catch(...)
是为了和throw;
一起使用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(...)
的正确方法
通用的exception捕获机制将非常有用。
疑。 您已经知道您的代码已损坏,因为它正在崩溃。 吃例外可能掩盖这一点,但这可能只会导致更加棘手,更微妙的错误。
你真正想要的是一个debugging器…
那么,如果你想赶上所有例外创build一个小型转储例如…
有人在Windows上做了这个工作。
这里是你可以捕捉到的列表:
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)中创build一个minidump
-
你可以从控制台窗口运行你的使用JNI的Java应用程序(从java命令行启动它)来查看在JVM崩溃之前是否有任何可能被检测到的报告。 如果直接作为Java窗口应用程序运行,则可能会丢失如果从控制台窗口运行而出现的消息。
-
其次,你可以存储你的JNI DLL实现,以显示你的DLL中的方法是从JNI进入,你正确地返回等?
-
为了防止问题出在C ++代码中的某个JNI接口方法的错误使用上,您是否证实了一些简单的JNI示例可以编译并使用您的设置? 我特别想到使用JNI接口方法将参数转换为本机C ++格式,并将函数结果转换为Javatypes。 对这些数据进行存根是很有用的,以确保数据转换正在工作,并且不会像COM一样调用JNI接口。
-
还有其他的东西需要检查,但是如果不知道更多关于你的本地Java方法以及它们的JNI实现是怎么做的,那么很难提出build议。 从C ++代码级别捕获exception与您的问题有关。 (您可以使用JNI接口将exception重新抛出为Java,但是从您提供的内容中可以看出,这不是很清楚。
对于无法正确debugging使用JNI的程序的真正问题(或者在debugging器下运行时没有出现该错误):
在这种情况下,在你的JNI调用(即所有本地方法都是私有方法,以及你的类中的公共方法调用它们)中添加Java包装通常会有所帮助,这些方法会进行一些基本的完整性检查(检查所有“对象”是否已释放,释放后不使用)或同步(只是将所有方法从一个DLL同步到单个对象实例)。 让java包装方法logging错误并引发exception。
这通常会比试图debugging一个大规模并行Java程序更容易find真正的错误(令人惊讶的是,大部分Java代码中不遵守被调用函数的语义,导致一些令人讨厌的双释放或类似错误)本地debugging器…
如果你知道原因,把代码保存在你的包装方法中,避免它。 最好是你的包装方法抛出的exception比你的JNI代码崩溃的VM …