【问题标题】:Win32 Thread Exits UnexpectedlyWin32 线程意外退出
【发布时间】:2010-05-09 10:42:08
【问题描述】:

我正在编写一个 C++ 应用程序。我意识到我的一个工作线程可能会意外终止。 (VS 2005)调试日志说:

线程“Win32 线程”(0x5d98)有 退出代码 -858993460 (0xcccccccc)。

我用 try/catch 块包围了所有工作线程代码。所以,如果原因是一个例外,我会抓住它。但我不能:

try{
   ...
   Connection* conn = connectionPool->getConnection(); // unexpected exit occurs here
   ...
} catch(exception& e) {
   ...
}

我有十个线程同时运行,一段时间后只有一个线程崩溃,而其他线程继续运行(并获得新的 [OCCI] 连接)。

是否存在未被“异常”捕获的异常类型?或者我对线程/异常有什么不了解?

谢谢。

【问题讨论】:

    标签: c++ exception winapi multithreading


    【解决方案1】:

    并非所有错误都会引发可以使用 C++ try...catch 机制捕获的 C++ 异常。例如,除以零不会引发 C++ 异常,但会导致未定义的行为,这很可能使您的应用程序退出。

    但是,您的代码可能会抛出不是从 std::exception 派生的东西,因此您可能需要重写:

    try{
       Connection* conn = connectionPool->getConnection(); // unexpected exit occurs here
    } 
    catch(exception& e) {
        // handle things derived from std::exception
    }
    catch ( ... ) {
       // handle things that are not so derived
    }
    

    它将处理诸如throw "eeek!";之类的事情

    同样,但与问题无关,您通常应该通过 const 引用捕获异常。

    【讨论】:

    • 我怎样才能捕捉到这种意想不到的异常呢?所以我的线程不会在我不知情的情况下退出。
    • @sahs 一般来说,你不能——你必须编写你的代码,这样这样的错误就不会发生。例外并不是适用于糟糕代码的创可贴。
    • @Neil 我正在使用 OCCI 库来获取连接,这就是发生异常的地方。当其中一个意外退出时,所有其他线程都可以获得连接。无论如何,您的建议可能会解决问题。我正在尝试,谢谢。
    • 它没有解决:(。仍然线程没有捕获任何异常。现在是时候试试 PiotrLegnica 所说的了。
    【解决方案2】:

    有没有被“异常”捕获的异常类型?

    是的,SEH 例外。要捕获它们,您需要使用__try/__except MSVC 扩展(请参阅Structured Exception Handling),或编写全局 SEH/VEH 处理程序(请参阅SetUnhandledExceptionFilterAddVectoredExceptionHandler)。

    【讨论】:

    • 你确定吗?您给出的第一个链接说:“C++ 异常处理机制更加灵活,因为它可以处理任何类型的异常。”
    • @sahs:适用于自定义代码。 Windows 使用 SEH 报告其异常(如被零除或访问冲突)。但是,如果您使用正确的 /EH 编译,它们可以被 catch(...) 捕获。要使用普通的catch,您需要先将它们转换为 C++ 异常,如另一个答案中所述。
    【解决方案3】:

    找到问题的最简单方法是在调试器下运行您的应用程序并启用 Win32 异常中断。每当遇到 Win32 异常时,应用程序就会进入调试器,您可以找出问题所在。

    如果你不是在调试,想要捕捉一个win32结构化异常,你必须使用_set_se_translator api来设置一个翻译函数。每当出现 Win32 异常并且您有机会将其转换为您选择的 C++ 异常时,都会调用已注册的函数。

    【讨论】:

    • 对,但是如果线程抛出异常,它会中断吗?据我所知,它没有..?
    • 是的,如果它是 Win32 异常。如果它是 C++ 异常,您还必须启用 C++ 异常。
    • 我刚刚检查了调试器设置(VS2005),所有“用户未处理”的异常类型已经破坏了应用程序。你认为这意味着线程不会因为异常而终止吗?终止的其他原因是什么?
    • 如果您熟悉windbg,请尝试运行附加到它的应用程序。在 windbg 中,您可以在 Exit Thread 事件中启用中断执行。
    【解决方案4】:

    catch(exception& e) 捕获派生自 std::exception 的 C++ 异常,仅此而已。

    它不会捕获不是从该类派生的 C++ 异常(例如,如果我这样做 throw 42,它将不会被捕获),并且它不会捕获异常或系统级别的错误。

    Windows 使用结构化异常处理 (SEH) 来发出错误信号,而这些错误不会被普通的 C++ catch 语句捕获。这可能包括除以零之类的错误,以及访问冲突或几乎任何其他可能在操作系统或硬件级别出错的问题。

    The docs 很好地解释了如何捕获 SEH 异常。

    【讨论】:

      【解决方案5】:

      我发现了一条重要线索。当您使用 CloseHandle 函数关闭句柄时,线程以代码 0xCCCCCCCC 退出。在这条线索的帮助下,我意识到在非常罕见的情况下,即使线程正在工作,我也会关闭线程的句柄。为什么它在获得连接时完全退出?那也有解释,不过和代码的结构有关,这里可能很难解释。

      感谢大家在例外问题上与我进行头脑风暴:$。

      【讨论】:

        猜你喜欢
        • 2021-07-27
        • 1970-01-01
        • 1970-01-01
        • 2014-05-25
        • 1970-01-01
        • 2020-05-19
        • 2017-08-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多