catch(...) 没有捕获异常,我的程序仍然崩溃

Posted

技术标签:

【中文标题】catch(...) 没有捕获异常,我的程序仍然崩溃【英文标题】:catch(...) is not catching an exception, my program is still crashing 【发布时间】:2014-06-25 22:37:15 【问题描述】:

我的应用程序在初始化时崩溃的测试仪出现问题。我添加了更多的日志记录和异常处理,但它仍然崩溃并显示通用的“此程序已停止工作”消息,而不是触发我的错误处理。

鉴于我的 main() 看起来像这样并且有 catch(...) 在什么情况下不会触发?

try
    simed::CArmApp app(0, cmd);
    for(bool done = false;!done;) 
    
        done = !app.frame();
    
 catch(const std::runtime_error &e)
    handleApplicationError(e.what());
    return -1;
 catch(...) 
    handleApplicationError("Unknown Error");
    return -999;

我的代码正在调用执行 OpenGL 渲染的库,我认为这是出了问题。

【问题讨论】:

我不确定我是否理解。你怎么知道这是一个未捕获的异常? 因为 handleApplicationError 没有被调用(它引发了一个 MessageBox 并杀死了我的启动画面,这些都没有发生) 但是为什么不能只是其他类型的程序崩溃呢? 对不起,我误会了。我的理解是catch(...) 应该让我在 任何事情 出错时让我重新获得控制权,或者更确切地说,我在问在什么情况下 是真的。 啊,不。在 C++ 中,异常是一种非常特殊的编程语言机制。这不像是硬件例外。您必须专门使用throw 语句来引发异常。因此,例如,任何类型的未定义行为(如空指针取消引用等)通常不会导致抛出 C++ 异常。 【参考方案1】:

如果 C++ catch(...) 块没有捕获错误,可能是因为 Windows 错误。

在 Windows 上有一个名为 Structured Exception Handling 的概念,当坏事发生时操作系统会引发“异常”,例如取消引用无效的指针、除以零等。我说“异常”是因为这些不是 C++例外;相反,这些是 Windows 以 C 风格定义的严重错误 - 这是因为 Win32 是用 C 编写的,因此 C++ 异常不可行。

另见:

Difference between a C++ exception and Structured Exception try-except Statement Method of getting a stack trace from an EXCEPTION_POINTERS struct

基于 cmets 的更新

如果您同时需要 C++ 异常处理和 SEH,也许您可​​以尝试以下(未经测试的)代码:

__try

    try
    
        // Your code here...
    
    catch (std::exception& e)
    
        // C++ exception handling
    

__except(HandleStructuredException())

    // SEH handling 

【讨论】:

很有趣,谢谢。目前尚不清楚我如何尝试实现两者 - 或者更确切地说在我的示例代码中我应该如何编写它以更安全。我相信 3rd-party lib 是问题所在 - 该 lib 确实会引发 C++ 异常,所以我希望他们为我发现了这些问题!您是否可以以我的代码为例,作为一个完美的答案? 我已经添加了一些示例代码,也许这可以用来捕获这两种异常 yuck(必须这样做,而不是你的代码!)但似乎这是解决方案 结构化异常处理(__try__except__finally)和C++异常处理(trycatch)不能在同一个函数中使用。请注意,处理结构化异常是正确的做法是非常【参考方案2】:

如果由于堆栈展开以处理不同的异常而被销毁的对象的析构函数引发异常,则程序将退出,catch(...) 与否。

【讨论】:

【参考方案3】:

据我所知,至少有两种情况catch(...)实际上无法捕获

    超过 1 个未处理的异常:在处理之前发生的异常之前引发异常,则 c++ 无法处理它,应用程序将崩溃。 抛出不在异常规范列表中的异常:如果任何方法抛出了不在异常规范列表中的异常(在任何中),则将调用unexpected致电abort

【讨论】:

+1,但在第 1 种情况下,这不仅仅是一次“崩溃”,而是对std::terminate 的调用。 @Angew,对,事实上terminate默认也会调用abort,所以和#2一样。 我想更清楚一点,#2 还包括你的投掷函数是否被其他函数调用,和/或任一函数被声明为noexcept。如果正确指定了 throwing 函数但它被 noexcept 函数调用,则调用者将终止。这可能是基本的,但它只花了我几分钟的时间,所以!【参考方案4】:

您声明了任何全局对象吗? 如果您在主循环之外创建了任何对象,这可以解释为什么它没有被捕获(它不在您的 try-catch 中)。

【讨论】:

它肯定是由于从 try/catch 块内部调用的东西而崩溃 - 我得到日志以证明代码正在运行,然后它就死了,但我的错误处理都没有被触发:(跨度>

以上是关于catch(...) 没有捕获异常,我的程序仍然崩溃的主要内容,如果未能解决你的问题,请参考以下文章

GCC 程序中没有捕获异常

不捕获向量的异常

捕获未处理的异常

为啥使用Try,Catch捕获异常,程序依然Crash

java —— 异常

雪花程序没有被 catch 块捕获