// Throw an exception. This should unwind the StackThingy// object, calling its destructor.throwCException();}

When I run this code, Point A executes in the constructor, but execution
never reaches Point B. It should, because the exception being thrown should unwind
stack, calling the destructors on any stack-allocated object.
But somehow, the exception would not properly destroy the thingy object.

I narrowed it down to the __stdcall calling convention. If I remove the __stdcall
declaration to make it a regular C++ function, then the destructor is called as I
would expect. I can find no mention of this behavior in the docs or on the wider web.
The description of __stdcall talks about stack maintenance as a key difference between
calling conventions, but doesn't describe exception handling at all.

Is this expected behavior, or is there some other nefarious factor at work here?

Comments

Interesting... Does the throw actually occur? What happens if you wrap your call to MyTestRoutine in a try/catch block? Or add a debugging print statement after the throw?

It'd be shocking if throw turns into a nop in this case, but not much less shocking than the destructor not being called...

I had no luck finding information about this problem either.

BTW, what happens if an __stdcall routine is in the middle of a "normal" call chain, and the lower "normal" function throws? Does unwinding happen correctly across the __stdcall?

Obviously, I should test all these questions myself, but Visual C++ seems to be missing from this Linux box :)

Sylvain Galineau 9:21 AM on 29 Jul 2004

I haven't messed with this in too long but I think __stdcall has the callee cleaning up the stack. If that's the case, could this conflict with the back-end unwinding logic by removing from the frame what it needs to walk up the chain of destructors inside the caller ? If the default calling convention has the caller cleaning up the stack, we can assume something is being removed that shouldn't be.

I'd suggest e-mailing Raymond Chen...C++ exception handling and how it maps to/works with Win32's Structure Exception Handling is a rather complex realm.

I've never seen a difference with parens or without; it's supposed to be the same either way. Of course, this whole topic is about a C++ compiler dropping the ball on C++ semantics, so all bets are off.

To be more specific, could it be that the function declaration is declared __stdcall and the function definition it is not? Or vice versa? I could envision this problem being caused by the resulting linking issues.

Note that the Microsoft docs don't explicitly say that the definition and declaration both include the __stdcall keyword, but the fact that __stdcall changes the calling conventions makes it seem likely that both are required.

Sylvain Galineau 2:40 PM on 31 Jul 2004

Wow. That's a different story. The behavior of that is undefined. See here : "/GX enables support for synchronous (also called typed or C++) exception handling with the assumption that extern C functions don't throw C++ exceptions. "

Later on....:

"Finally, let's consider whether we can assume that extern "C" functions don't throw C++ exceptions (remember that such an assumption is built into /GX). Extern "C" functions in a C++ program are most likely being linked in from an object module or library. These functions are often written in a different language, such as C or assembler. Because the type of exception we are handling is a feature specifically of the C++ language only, it seems a reasonable assumption to say that an extern "C" function will not throw an exception.

Of course, if an extern "C" function is compiled by the C++ compiler, it is perfectly legal for that function, or one of its called functions, to throw a C++ exception. For those who must throw C++ exceptions from extern "C" functions, replace /GX, which is the same as using /EHsc, with just /EHs. /EHs enables C++ exception handling without the assumption that extern "C" functions will never throw a C++ exception. /EHc enables the assumption that extern "C" functions do not throw exceptions."