捕获未知异常

Posted

技术标签:

【中文标题】捕获未知异常【英文标题】:catching unknown exception 【发布时间】:2011-07-08 13:21:43 【问题描述】:

在我的代码的发布版本中,有一行抛出异常,我不知道它是什么类型的异常,所以我无法正确捕获它或找出问题所在。

我使用了 catch(...) 但这几乎毫无价值。

这是一些伪代码

 try
  
    m_mmwIPC = gcnew NiftyIPC(gcnew String("Monitor"), true);
  
  catch (CException* e)
  
    TCHAR   szCause[255];
    e->GetErrorMessage(szCause, 255);
    CString errorStr = szCause;
    RemoveLineFeeds(errorStr);
    OutputDebugString(errorStr);
  
  catch(...)
  
    OutputDebugString(L"Unknown exception\n");
  

那么,有什么方法可以获取有关引发的未知异常的任何详细信息?只是一个类型就很好了。

谢谢

【问题讨论】:

(我的脑海里突然闪过一个偶然的想法)很遗憾,C++0x auto 的措辞是“从它的 initializer 中扣除的”,而且那里尽管类型对编译器来说或多或少是显而易见的,但这里确实不是初始化器。否则可以写catch(auto excpt)。当然,对于必须生成所有这些单独的代码路径的编译器来说,这可能是一个巨大的负担...... 【参考方案1】:

不是真的,它可能是 intconst char*RhubarbPie über-smart 指针。

但是:

也尝试捕捉std::exception。这将捕获大量 C++ 原生异常。 您的异常可能是 .NET 异常,因此请尝试捕获该异常,而不是 MFC 基础异常。 (看起来您正在使用 C++/CLI。在这种情况下,.NET 异常最终会出现在 catch-all 子句中) 此外,异常通常意味着在 C++ 中通过引用来捕获 (更新:MFC 显然通过指针使用 throw-and-catch。只要你捕捉到抛出的东西,它也可以工作。) 使用 __try 和 __catch 也可能会有所帮助,因为堆栈溢出、访问冲突等一些“硬件”异常在 Windows 上也是未知异常。捕获它们的语法略有不同,但您会得到一个异常标识符,可用于报告引发的异常类型。我用它来打印我们应用程序中致命错误的堆栈跟踪。

【讨论】:

尽管在 C++ 中通过引用更好地捕获是公平的,但我相信 MFC 倾向于遵循通过指针捕获的约定。这并不能阻止用户代码通过引用来捕获。 我认为这是我能做的最好的方法。尝试捕获所有泛型类型并尽我所能记录它们。 MFC 确实通过指针捕获,但这并不重要,因为在幕后引用只是一个指针。 @lunknown:好的。我不知道MFC。请注意,对 X 的引用和指向 X 的指针是与编译器无关的两种类型,因此 catch() 子句不会自动转换。如果异常是由指针引发的,则需要通过指针捕获,或者如果由值(或引用,我想)抛出,则需要通过引用捕获。【参考方案2】:

当您指定使用 MFC 时,我将假设您使用的是 Visual Studio 版本。如果是这种情况并且您能够在调试模式下运行程序,那么您可以将调试器设置为在未处理的异常上中断。这需要删除代码的catch(...) 部分,但它应该在正确的位置进入调试器,并为您提供有关异常本身的有用信息。

请参阅 Microsoft 文档 here 和 here。

【讨论】:

该异常仅在发布模式下发生,就像我似乎发现的所有丑陋错误一样。 @luknown:您可以在发布模式代码上运行调试器(尤其是如果您使用调试信息构建)。只是不要期望调试器在调试优化代码时正确报告堆栈上的值。【参考方案3】:

每个异常都应该派生自std::exception,然后您可以使用 RTTI。标准的 catch 块是

catch (const std :: exception & e) 
    // e .what ();
    // typeid (e);

catch (...) 
    // WTF ?!?!?

在 c++0x 中,您可以使用 std::current_exception 并可能将 exception_ptr 传递到一些聪明的库中进行分析。

请记住,异常可以是 buildins 和其他没有 RTTI 的类型,这就是为什么您应该始终从 std::exception 派生的原因。

【讨论】:

"每个异常都应该从 std::exception 派生":MFC 就是这种情况吗?我知道 CException 派生自 CObject - 它也派生自 std::exception 吗? 可能但不是必须的。检查NULL != dynamic_cast<const std::exception *>(CExecption_pointer) 实际上,如果你有上面的 catch 块,当且仅当它派生自 std::exception 时,你的 CException 对象才会绑定到它(并且如果没有更具体的匹配块首先潜入) 【参考方案4】:

不,这里不是。 catch( ...) 真的应该作为最后的手段使用。

【讨论】:

【参考方案5】:

一种选择是捕获错误并在调试器中运行程序员(这在发布模式下是可能的)。 Visual Studio 将闯入发生未捕获异常的代码。

【讨论】:

以上是关于捕获未知异常的主要内容,如果未能解决你的问题,请参考以下文章

Python基础学习错误与异常

python之-- 异常

java异常和错误码定义规范及其使用

基于未知情况的WSS失效异常数据预测判断方法

Java:抛出异常后如何终止执行后面的代码?

Java:抛出异常后如何终止执行后面的代码?