C++ 捕获所有异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/315948/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 14:35:03  来源:igfitidea点击:

C++ catching all exceptions

c++exception

提问by Obediah Stane

Is there a c++ equivalent of Java's

是否有 C++ 等价于 Java 的

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

I am trying to debug Java/jni code that calls native windows functions and the virtual machine keeps crashing. The native code appears fine in unit testing and only seems to crash when called through jni. A generic exception catching mechanism would prove extremely useful.

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

回答by Greg D

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

will catch all C++ exceptions, but it should be considered bad design. You can use c++11's new current_exception mechanism, but if you don't have the ability to use c++11 (legacy code systems requiring a rewrite), then you have no named exception pointer to use to get a message or name. You may want to add separate catch clauses for the various exceptions you can catch, and only catch everything at the bottom to record an unexpected exception. E.g.:

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

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

回答by Johannes Schaub - litb

Someone should add that one cannot catch "crashes" in C++ code. Those don't throw exceptions, but do anything they like. When you see a program crashing because of say a null-pointer dereference, it's doing undefined behavior. There is no std::null_pointer_exception. Trying to catch exceptions won't help there.

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

Just for the case someone is reading this thread and thinks he can get the cause of the program crashes. A Debugger like gdb should be used instead.

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

回答by bobah

This is how you can reverse-engineer the exception type from within catch(...)should you need to (may be useful when catching unknown from a third party library) with GCC:

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

and if you can afford using Boostyou can make your catch section even simpler (on the outside) and potentially cross-platform

如果您负担得起使用Boost,您可以使您的捕获部分更加简单(在外部)并且可能是跨平台的

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

回答by Greg Hewgill

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

Note that the ...inside the catchis a real ellipsis, ie. three dots.

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

However, because C++ exceptions are not necessarily subclasses of a base Exceptionclass, there isn't any way to actually see the exception variable that is thrown when using this construct.

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

回答by Clearer

it is not possible (in C++) to catch all exceptions in a portable manner. This is because some exceptions are not exceptions in a C++ context. This includes things like division by zero errors and others. It is possible to hack about and thus get the ability to throw exceptions when these errors happen, but it's not easy to do and certainly not easy to get right in a portable manner.

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

If you want to catch all STL exceptions, you can do

如果要捕获所有 STL 异常,可以执行

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

Which will allow you do use e.what(), which will return a const char*, which can tell you more about the exception itself. This is the construct that resembles the Java construct, you asked about, the most.

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

This will not help you if someone is stupid enough to throw an exception that does not inherit from std::exception.

如果有人愚蠢到抛出不继承自std::exception.

回答by Mellester

In short, use catch(...). However, note that catch(...)is meant to be used in conjunction with throw;basically:

简而言之,使用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
}

This is the proper way to use catch(...).

这是正确的使用方法catch(...)

回答by Infintyyy

it is possible to do this by writing:

可以这样写:

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

But there is a very not noticeable risk here: you can not find the exact type of error that has been thrown in the tryblock, so use this kind of catchwhen you are sure that no matter what the type of exception is, the program must persist in the way defined in the catchblock.

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

回答by John D. Cook

You can use

您可以使用

catch(...)

but that is very dangerous. In his book Debugging Windows, John Robbins tells a war story about a really nasty bug that was masked by a catch(...) command. You're much better off catching specific exceptions. Catch whatever you think your try block might reasonably throw, but let the code throw an exception higher up if something really unexpected happens.

但这是非常危险的。在他的Debugging Windows一书中,John Robbins 讲述了一个关于被 catch(...) 命令掩盖的非常讨厌的错误的War故事。你最好捕捉特定的异常。捕获您认为 try 块可能合理抛出的任何内容,但如果确实发生了意外情况,请让代码向上抛出异常。

回答by Paul Sonier

Let me just mention this here: the Java

让我在这里提一下:Java

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

may NOT catch all exceptions! I've actually had this sort of thing happen before, and it's insantiy-provoking; Exception derives from Throwable. So literally, to catch everything, you DON'T want to catch Exceptions; you want to catch Throwable.

可能无法捕获所有异常!我以前也遇到过这样的事情,真是发人深省;异常源自 Throwable。所以从字面上看,要捕获所有内容,您不想捕获异常;你想抓住 Throwable。

I know it sounds nitpicky, but when you've spent several days trying to figure out where the "uncaught exception" came from in code that was surrounded by a try ... catch (Exception e)" block comes from, it sticks with you.

我知道这听起来很挑剔,但是当您花了几天时间试图找出被 try ... catch (Exception e)" 块包围的代码中“未捕获的异常”来自哪里时,它坚持你。

回答by Aftershock

Well, if you would like to catch all exception to create a minidump for example...

好吧,如果您想捕获所有异常以创建小型转储,例如...

Somebody did the work on Windows.

有人在 Windows 上完成了这项工作。

See http://www.codeproject.com/Articles/207464/Exception-Handling-in-Visual-CplusplusIn the article, he explains how he found out how to catch all kind of exceptions and he provides code that works.

请参阅http://www.codeproject.com/Articles/207464/Exception-Handling-in-Visual-Cplusplus在文章中,他解释了他如何发现如何捕获所有类型的异常,并提供了有效的代码。

Here is the list you can catch:

这是您可以捕获的列表:

 SEH exception
 terminate
 unexpected
 pure virtual method call
 invalid parameter
 new operator fault 
 SIGABR
 SIGFPE
 SIGILL
 SIGINT
 SIGSEGV
 SIGTERM
 Raised exception
C++ typed exception

And the usage: CCrashHandler ch; ch.SetProcessExceptionHandlers(); // do this for one thread ch.SetThreadExceptionHandlers(); // for each thred

以及用法:CCrashHandler ch; ch.SetProcessExceptionHandlers(); // 为一个线程执行此操作 ch.SetThreadExceptionHandlers(); // 对于每个线程



By default, this creates a minidump in the current directory (crashdump.dmp)

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