捕获所有未处理的 C++ 异常?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/276102/
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
Catching all unhandled C++ exceptions?
提问by Fire Lancer
Is there some way to catch exceptions which are otherwise unhandled (including those thrown outside the catch block)?
有什么方法可以捕获未处理的异常(包括在 catch 块之外抛出的异常)?
I'm not really concerned about all the normal cleanup stuff done with exceptions, just that I can catch it, write it to log/notify the user and exit the program, since the exceptions in these casese are generaly fatal, unrecoverable errors.
我并不真正关心使用异常完成的所有正常清理工作,只是我可以捕获它,将其写入日志/通知用户并退出程序,因为这些情况下的异常通常是致命的、不可恢复的错误。
something like:
就像是:
global_catch()
{
MessageBox(NULL,L"Fatal Error", L"A fatal error has occured. Sorry for any inconvience", MB_ICONERROR);
exit(-1);
}
global_catch(Exception *except)
{
MessageBox(NULL,L"Fatal Error", except->ToString(), MB_ICONERROR);
exit(-1);
}
采纳答案by EvilTeach
This can be used to catch unexpected exceptions.
这可用于捕获意外异常。
catch (...)
{
std::cout << "OMG! an unexpected exception has been caught" << std::endl;
}
Without a try catch block, I don't think you can catch exceptions, so structure your program so the exception thowing code is under the control of a try/catch.
如果没有 try catch 块,我认为您无法捕获异常,因此请构建您的程序,以便异常抛出代码处于 try/catch 的控制之下。
回答by kralyk
Check out std::set_terminate()
回答by gbjbaanb
You can use SetUnhandledExceptionFilteron Windows, which will catch all unhandled SEH exceptions.
您可以在 Windows 上使用SetUnhandledExceptionFilter,它将捕获所有未处理的 SEH 异常。
Generally this will be sufficient for all your problems as IIRC all the C++ exceptions are implemented as SEH.
通常,这足以解决您的所有问题,因为 IIRC 所有 C++ 异常都作为 SEH 实现。
回答by paavo256
Without any catch block, you won't catch any exceptions. You can have a catch(...) block in your main() (and its equivalent in each additional thread). In this catch block you can recover the exception details and you can do something about them, like logging and exit.
没有任何 catch 块,您将不会捕获任何异常。您可以在 main() 中有一个 catch(...) 块(以及每个附加线程中的等效块)。在这个 catch 块中,您可以恢复异常详细信息,并且可以对它们执行一些操作,例如记录和退出。
However, there are also downside about a general catch(...) block: the system finds that the exception has been handled by you, so it does not give any more help. On Unix/Linux, this help would constitute creating a CORE file, which you could load into the debugger and see the original location of the unexcepted exception. If you are handling it with catch(...) this information would be already lost.
但是,通用 catch(...) 块也有缺点:系统发现异常已由您处理,因此不会提供更多帮助。在 Unix/Linux 上,此帮助将构成创建 CORE 文件,您可以将其加载到调试器中并查看无例外异常的原始位置。如果您使用 catch(...) 处理它,则此信息将已经丢失。
On Windows, there are no CORE files, so I would suggest to have the catch(...) block. From that block, you would typically call a function to resurrect the actual exception:
在 Windows 上,没有 CORE 文件,所以我建议使用 catch(...) 块。从该块中,您通常会调用一个函数来恢复实际的异常:
std::string ResurrectException()
try {
throw;
} catch (const std::exception& e) {
return e.what();
} catch (your_custom_exception_type& e) {
return e.ToString();
} catch(...) {
return "ünknown exception!";
}
}
int main() {
try {
// your code here
} catch(...) {
std::string message = ResurrectException();
std::cerr << "Fatal exception: " << message << "\n";
}
}
回答by paxos1977
Update: This covers c++98 only.
更新:这仅涵盖 c++98。
From More Effective C++by Meyers (pg 76), you could define a function that gets called when a function generates an exception that is not defined by its exception specification.
从Meyers 的More Effective C++(第 76 页)中,您可以定义一个函数,当函数生成未由其异常规范定义的异常时,该函数被调用。
void convertUnexpected()
{
// You could redefine the exception here into a known exception
// throw UnexpectedException();
// ... or I suppose you could log an error and exit.
}
In your application register the function:
在您的应用程序中注册函数:
std::set_unexpected( convertUnexpected );
Your function convertUnexpected() will get called if a function generates an exception that is not defined by its exception specification... which means this only works if you are using exception specifications. ;(
如果一个函数生成了一个未由其异常规范定义的异常,则您的函数 convertUnexpected() 将被调用……这意味着这仅在您使用异常规范时才有效。;(
回答by Martin York
This is what I always do in main()
这就是我在 main() 中经常做的
int main()
{
try
{
// Do Work
}
catch(std::exception const& e)
{
Log(e.what());
// If you are feeling mad (not in main) you could rethrow!
}
catch(...)
{
Log("UNKNOWN EXCEPTION");
// If you are feeling mad (not in main) you could rethrow!
}
}
回答by scrutari
Provided that C++11 is available, this approach may be used (see example from: http://en.cppreference.com/w/cpp/error/rethrow_exception):
如果 C++11 可用,则可以使用此方法(参见示例:http: //en.cppreference.com/w/cpp/error/rethrow_exception):
#include <iostream>
#include <exception>
void onterminate() {
try {
auto unknown = std::current_exception();
if (unknown) {
std::rethrow_exception(unknown);
} else {
std::cerr << "normal termination" << std::endl;
}
} catch (const std::exception& e) { // for proper `std::` exceptions
std::cerr << "unexpected exception: " << e.what() << std::endl;
} catch (...) { // last resort for things like `throw 1;`
std::cerr << "unknown exception" << std::endl;
}
}
int main () {
std::set_terminate(onterminate); // set custom terminate handler
// code which may throw...
return 0;
}
This approach also allows you to customize console output for unhandled exceptions: to have something like this
这种方法还允许您为未处理的异常自定义控制台输出:有这样的东西
unexpected exception: wrong input parameters
Aborted
instead of this:
而不是这个:
terminate called after throwing an instance of 'std::logic_error'
what(): wrong input parameters
Aborted
回答by ididak
Use catch (...) in all of your exception barriers (not just the main thread). I suggest that you always rethrow (...) and redirect standard output/error to the log file, as you can't do meaningful RTTI on (...). OTOH, compiler like GCC will output a fairly detailed description about the unhandled exception: the type, the value of what() etc.
在所有异常障碍(不仅仅是主线程)中使用 catch (...)。我建议你总是重新抛出 (...) 并将标准输出/错误重定向到日志文件,因为你不能在 (...) 上做有意义的 RTTI。OTOH,像 GCC 这样的编译器会输出关于未处理异常的相当详细的描述:类型、what() 的值等。