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

时间:2012-01-18 00:51:03

标签: c++ winapi exception

我刚问this question。简而言之,当你从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 Here\n");
}

我尝试通过简单地抛出/捕获C ++异常(即删除win32计时器回调变量)来重新创建它,并且CFoo的向量破坏就好了。出于某种原因,析构函数不会在这里被称为向量中的东西。是什么赋予了?对此有合理的解释,还是只是奇怪,或者两者兼而有之?

1 个答案:

答案 0 :(得分:6)

你永远不应该允许异常传播到C API边界(比如SetTimer回调)。 C代码(和Windows API函数)对C ++语言异常一无所知。您不能依赖此类代码来传播您的例外。

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

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