C ++捕获所有异常

问题描述 投票:211回答:14

是否有Java的c ++等价物

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

我正在尝试调试调用本机Windows函数的Java / jni代码,并且虚拟机不断崩溃。本机代码在单元测试中看起来很好,并且在通过jni调用时似乎只会崩溃。一般的异常捕获机制将证明是非常有用的。

c++ exception
14个回答
299
投票
try{
    // ...
} catch (...) {
    // ...
}

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

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

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

默认情况下,这会在当前目录中创建一个minidump(crashdump.dmp)


4
投票

一般的异常捕获机制将证明是非常有用的。

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

你真正想要的是一个调试器......


2
投票
  1. 您是否可以从控制台窗口运行使用JNI的Java应用程序(从java命令行启动它),以查看是否有任何关于在JVM崩溃之前可能检测到的内容的报告。直接作为Java窗口应用程序运行时,如果从控制台窗口运行,则可能会丢失将显示的消息。
  2. 其次,你可以存根你的JNI DLL实现,以显示你的DLL中的方法是从JNI输入,你正在返回,等等?
  3. 如果问题是不正确地使用C ++代码中的一个JNI接口方法,您是否已经验证了一些简单的JNI示例是否可以编译并使用您的设置?我正在考虑使用JNI接口方法将参数转换为本机C ++格式并将函数结果转换为Java类型。将这些转换为确保数据转换正常工作并且您不会在类似COM的JNI接口调用中出现问题是很有用的。
  4. 还有其他事情需要检查,但如果不了解更多有关您的本机Java方法以及它们正在尝试执行的JNI实现的内容,则很难提出任何建议。目前尚不清楚从C ++代码级别捕获异常与您的问题有关。 (您可以使用JNI接口将异常重新抛出为Java,但是从您提供的内容中可以看出这将有所帮助。)

1
投票

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

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

这通常有助于找到真正的错误(这令人惊讶地主要在Java代码中,它不遵守被调用函数的语义导致一些讨厌的双重释放或类似)比试图调试大规模并行Java程序更容易本机调试器......

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


0
投票

那真的取决于编译环境。 gcc没有抓住这些。 Visual Studio和我用过的最后一个Borland。

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

C ++规范说catch(...)必须捕获任何异常,但并非在所有情况下都如此。

至少从我的尝试。


128
投票

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

只是因为有人正在阅读这个帖子,并认为他可以得到程序崩溃的原因。应该使用像gdb这样的调试器。


56
投票
try {
   // ...
} catch (...) {
   // ...
}

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

但是,因为C ++异常不一定是基本Exception类的子类,所以没有任何方法可以实际查看使用此构造时引发的异常变量。


49
投票

如果您需要(在从第三方库中捕获未知时可能很有用),您可以使用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;
}

34
投票

不可能(在C ++中)以可移植的方式捕获所有异常。这是因为某些异常在C ++上下文中不是异常。这包括除零错误等等。当这些错误发生时,有可能破解并因此获得抛出异常的能力,但这并不容易,并且当然不容易以可移植的方式获得正确。

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

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

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

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


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(...)的正确方法。


18
投票

可以这样写:

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

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


17
投票

您可以使用

catch(...)

但那非常危险。在他的书Debugging Windows中,约翰罗宾斯讲述了一个关于一个非常讨厌的错误的战争故事,这个错误被一个catch(...)命令所掩盖。捕获特定异常会更好。抓住你认为你的try块可能合理抛出的任何东西,但是如果出现意外的事情,让代码抛出更高的异常。


12
投票

我在这里只提一下:Java

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

可能无法捕获所有异常!事实上,我之前已经发生过这样的事情,而且这是令人厌恶的;异常来自Throwable。从字面上看,要抓住一切,你不要想抓住例外;你想抓住Throwable。

我知道这听起来很挑剔,但是当你花了几天的时间试图找出“未被捕获的异常”来自代码的地方时,其中包含了一个尝试...捕获(例外e)“块来自,它坚持您。

© www.soinside.com 2019 - 2024. All rights reserved.