I just asked this question. In short, when you throw from a win32 timer callback, the exception doesn’t appear to go anywhere. It seems to be surreptitiously handled by Windows somewhere.
OK well thats a problem. The OTHER side of the problem is that destructors don’t seem to be getting called when this exception IS thrown. In the following code, for the std::vector of CFoo, the only time “~CFoo” is output is when the temporaries in GetFooVect are destructed and when the rValue is copied to fooVect. The contents of fooVect are NOT destructed.
This is my worst nightmare. I use RAII pretty heavily. I lean pretty heavily on my destructors to cleanup appropriately.
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");
}
I’ve tried recreating this by simply throwing/catching C++ exceptions (ie removing the win32 timer callback variable) and the vector of CFoo’s destructs just fine. For some reason, destructors are NOT being called here for things in vectors. What gives? Is there a logical explanation for this, or is it just weird, or both?
You should never, ever allow am exception to propagate across a C API boundary (like the SetTimer callback). C code (and the Windows API functions) know nothing about C++ language exceptions. You cannot rely on such code to propagate your exceptions.
Your callback should catch all C++ language exceptions before returning and handle the exceptions appropriately. If you need to somehow communicate the exceptions to the rest of your application, you need to do so yourself.
(Someone else here may be able to explain in detail what is happening in this case, but the short answer is that you can’t rely on C code to do the right thing in the presence of a C++ language exception, because it has no idea what a C++ language exception is.)