为什么从 win32 计时器回调抛出时不调用我的析构函数?

Why aren't my destructors called when throwing from a win32 timer callback?

本文关键字:调用 我的 析构函数 win32 计时器 回调 为什么      更新时间:2023-10-16

我刚刚问了这个问题。简而言之,当您从win32计时器回调中抛出时,异常似乎不会出现在任何位置。它似乎是由Windows在某个地方秘密处理的。

好吧,那是个问题。问题的另一面是,当抛出此异常时,似乎不会调用析构函数。在下面的代码中,对于CFoo的std::vector,输出"~CFoo"的唯一时间是GetFooVect中的临时性被破坏以及rValue被复制到fooVect时。fooVect的内容未被破坏。

这是我最可怕的噩梦。我大量使用RAII。我非常依赖我的析构函数来进行适当的清理。

class CFoo
{
public:
    ~CFoo() {printf(__FUNCTION__ "n");}
};
std::vector< CFoo > GetFooVect()
{
    std::vector< CFoo > rValue;
    rValue.push_back(CFoo());
    rValue.push_back(CFoo());
    rValue.push_back(CFoo());
    return rValue;
}
VOID CALLBACK Timer(HWND hwnd,
    UINT uMsg,
    UINT_PTR idEvent,
    DWORD dwTime)
{
    // My destructors aren't called?
    std::vector< CFoo> fooVect = GetFooVect();
    // I'm destroyed
    CFoo aFoo;
    throw FooExcept();
    printf("Also Heren");
}

我试着通过简单地抛出/捕获C++异常(即删除win32定时器回调变量)和CFoo的析构函数向量来重新创建它。出于某种原因,这里没有为向量中的东西调用析构函数。什么东西?这有一个合乎逻辑的解释吗,或者只是奇怪,或者两者兼而有之?

您永远不应该允许异常在C API边界上传播(如SetTimer回调)。C代码(以及Windows API函数)对C++语言异常一无所知。您不能依赖这样的代码来传播您的异常。

回调应该在返回之前捕获所有C++语言异常,并适当地处理这些异常。如果您需要以某种方式将异常传达给应用程序的其余部分,那么您需要自己这样做。

(这里的其他人可能能够详细解释这种情况下发生了什么,但简单的答案是,在C++语言异常的情况下,你不能依靠C代码来做正确的事情,因为它不知道C++语言异常是什么。)