[英]Catching all unhandled C++ exceptions?
有没有办法捕获原本未处理的异常(包括那些在catch块之外抛出的异常)?
我并不是真的关心所有正常的清理工作,只是因为我可以捕获它,将其写入日志/通知用户并退出程序,因为这些情况下的例外通常是致命的,不可恢复的错误。
就像是:
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);
}
这可用于捕获意外的异常。
catch (...)
{
std::cout << "OMG! an unexpected exception has been caught" << std::endl;
}
如果没有try catch块,我认为你不能捕获异常,所以构造你的程序,以便异常的代码在try / catch的控制之下。
您可以在Windows上使用SetUnhandledExceptionFilter ,它将捕获所有未处理的SEH异常。
通常,这对于您的所有问题都已足够,因为IIRC将所有C ++异常实现为SEH。
没有任何catch块,您将不会遇到任何异常。 你可以在main()中使用catch(...)块(以及每个附加线程中的等效块)。 在此catch块中,您可以恢复异常详细信息,并且可以对它们执行某些操作,例如记录和退出。
但是,一般的catch(...)块也存在缺点:系统发现异常已由您处理,因此它不再提供任何帮助。 在Unix / Linux上,此帮助将构成一个CORE文件,您可以将其加载到调试器中并查看未触发异常的原始位置。 如果你用catch(...)处理它,这些信息就会丢失。
在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";
}
}
更新 :这仅涵盖c ++ 98。
从Meyers的更有效的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.
}
在您的应用程序中注册功能:
std::set_unexpected( convertUnexpected );
如果函数生成一个未由其异常规范定义的异常,则会调用您的函数convertUnexpected()...这意味着只有在使用异常规范时这才有效。 (
这是我总是在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!
}
}
如果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;
}
此方法还允许您为未处理的异常自定义控制台输出:具有类似的内容
unexpected exception: wrong input parameters
Aborted
而不是这个:
terminate called after throwing an instance of 'std::logic_error'
what(): wrong input parameters
Aborted
在所有异常障碍(不仅仅是主线程)中使用catch(...)。 我建议你总是重新抛出(...)并将标准输出/错误重定向到日志文件,因为你不能在(...)上做有意义的RTTI。 OTOH,像GCC这样的编译器将输出关于未处理异常的相当详细的描述:类型,what()的值等。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.