我刚问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的向量破坏就好了。出于某种原因,析构函数不会在这里被称为向量中的东西。是什么赋予了?对此有合理的解释,还是只是奇怪,或者两者兼而有之?
答案 0 :(得分:6)
你永远不应该允许异常传播到C API边界(比如SetTimer回调)。 C代码(和Windows API函数)对C ++语言异常一无所知。您不能依赖此类代码来传播您的例外。
您的回调应该在返回之前捕获所有C ++语言异常并适当地处理异常。如果您需要以某种方式将异常传达给应用程序的其余部分,则需要自己执行此操作。
(这里的其他人可能能够详细解释在这种情况下发生了什么,但简短的回答是你不能依赖C代码在存在C ++语言异常的情况下做正确的事情,因为它不知道C ++语言异常是什么。)