当前位置:  开发笔记 > 编程语言 > 正文

C++捕获所有异常

如何解决《C++捕获所有异常》经验,为你挑选了11个好方法。

是否有Java的c ++等价物

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

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



1> Greg D..:
try{
    // ...
} catch (...) {
    // ...
}

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

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


通过const引用捕获异常是一种很好的做法.如:catch(std :: exception const&ex){/*...*/}
@omatai:已修复,它将捕获所有C++异常.除以零是未定义的行为,不会生成C++异常.
-1:这将"捕获C++中的所有异常"的建议具有误导性.尝试在try块内生成除零错误.您将看到它将生成一个未捕获的异常,但代码显然是在C++中.说明这将"捕获所有C++异常"然后在有限用途的注释中添加一些结构化异常会更有帮助.
避免不必要的副本是一个好处.
@coryan:为什么通过const引用捕获是一个好习惯?
@omatai它可能看起来很有误导性,但它仍然是准确的.除以零会产生一个信号; 它不会抛出异常.两者是不同的,语言有两个术语.
@coryan,谢谢你的提醒.我最近在C#land上花了太多时间.:)
但是你可以使用Windows`__try {} __except()`来捕获所有异常,甚至是通常会使应用程序崩溃的硬件信号.检查https://msdn.microsoft.com/en-us/library/s58ftw19.aspx和https://msdn.microsoft.com/en-us/library/ms681409(v=vs.85).aspx
啊,但这是一个关于C++的问题,而不是关于特定于平台的扩展.
@TimMB的另一个主要优点是,它不会导致对异常对象进行切片,因此像`what()`这样的虚函数实际上可以工作。

2> Johannes Sch..:

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

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


您可以在Windows上使用SEH捕获段错误,在POSIX系统上捕获信号(2)/ sigaction(2),这涵盖了当今使用的绝大多数系统,但是像异常处理一样,它不应该用于正常流控制.它更像是"在死前做一些有用的事情".
是的SEH.但是没有理智的标准c ++技术:)如果你坚持使用Windows,你几乎可以做任何事:)
好吧,正如Shy指出的那样,VC编译器是可能的.这不是一个好主意,但它是可能的.

3> bobah..:

这是你可以在catch(...)需要时从内部对异常类型进行反向工程的方法(在从第三方库中捕获未知时可能很有用):

#include 

#include 
#include 
#include 

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> Greg Hewgill..:
try {
   // ...
} catch (...) {
   // ...
}

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

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


在C++ 11中有:try {std :: string().at(1); //这会生成一个std :: out_of_range} catch(...){eptr = std :: current_exception(); //捕捉}
@bfontaine:是的,但是我说过要区分`catch`说明符和注释中的现有代码占位符(`// ...`),这显然不是C++语法.

5> Clearer..:

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

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

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

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

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



6> 小智..:

简而言之,使用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(...).


最好使用RAII进行内存管理,自动处理这种异常情况.
@MelleSterk在那种情况下堆栈是否仍然会被清理掉,这会运行`Foo`的析构函数?我认为这是RAII的重点.但是,如果你需要一个指向`Foo`的指针,而不仅仅是在堆栈上创建`Foo`,那么你需要将指针包装在堆栈中声明的其他东西上.

7> Infintyyy..:

可以这样写:

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

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


我希望你在提供优质答案后差不多5年就能回答一个问题获得某种徽章!
@DrEval如你所愿;)/sf/ask/17360801/?userid=2580505

8> John D. Cook..:

您可以使用

catch(...)

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



9> Paul Sonier..:

我在这里只提一下:Java

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

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

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


我们有一个非常严重的错误,因为捕获(Throwable)块而不是让它杀死东西而捕获OutOfMemoryError ...
当然,你永远不应该捕获Error对象 - 如果你应该捕获它们,那么它们将是异常.错误对象是完全致命的东西,例如用尽堆空间等.
@OscarRyz听起来像`CoderMalfunctionError`(它实际上是一个真正的Java`Error`子类......虽然它并不意味着它听起来像.)

10> Aftershock..:

好吧,如果你想捕获所有异常来创建一个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)



11> Shog9..:

通用的异常捕获机制将被证明非常有用。

疑。您已经知道您的代码已损坏,因为它崩溃了。饮食异常可能掩盖了这一点,但这可能只会导致甚至更原始,更微妙的错误。

您真正想要的是调试器...


我不同意,在实时应用程序中有很多情况,我宁愿捕获未知的异常,将“任何内容”写到日志中/采取一些常规的错误措施,而不是使应用程序崩溃。
我宁愿怀疑您正在考虑以下情况,您可以*采取一些常规的错误措施,而忽略那些浪费堆栈或内存已耗尽并且常规错误处理也不会成功的情况。您可以*从中恢复的捕获错误没有任何问题,但是恕我直言,捕获程序实际上应该仅在隔离(独立的堆栈,预分配的内存),程序终止前调用的精心编写的逻辑中存在。如果您不知道问题出在哪里,就无法确定可以从中解决问题。
推荐阅读
周扒pi
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有