捕获所有未处理的C ++异常?

时间:2008-11-09 16:51:02

标签: c++ exception exception-handling

是否有某种方法可以捕获未处理的异常(包括那些在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);
}

8 个答案:

答案 0 :(得分:25)

这可用于捕捉意外的异常。

catch (...)
{
    cout << "OMG! an unexpected exception has been caught" << endl;
}

如果没有try catch块,我认为你不能捕获异常,所以构建你的程序,所以异常的代码是在try / catch的控制之下。

答案 1 :(得分:19)

答案 2 :(得分:10)

您可以在Windows上使用SetUnhandledExceptionFilter,这将捕获所有未处理的SEH例外。

通常,这对于您的所有问题都已足够,因为IIRC将所有C ++异常都实现为SEH。

答案 3 :(得分:8)

没有任何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";
   }
}

答案 4 :(得分:7)

更新:这仅涵盖c ++ 98。

来自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.
}

在您的应用程序中注册功能:

std::set_unexpected( convertUnexpected );

如果函数生成未由其异常规范定义的异常,则会调用您的函数convertUnexpected()...这意味着只有在使用异常规范时才能使用此函数。 ;(

答案 5 :(得分:4)

这是我在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! 
    }
}

答案 6 :(得分:4)

如果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

答案 7 :(得分:1)

在所有异常障碍(不仅仅是主线程)中使用catch(...)。我建议你总是重新抛出(...)并将标准输出/错误重定向到日志文件,因为你不能在(...)上做有意义的RTTI。 OTOH,像GCC这样的编译器将输出关于未处理异常的相当详细的描述:类型,what()等的值。