Unpacking a stack for structured exceptions

This question gives more clarity on the problem described here . I did some more research and found that stack promotion does not occur in the following code fragment:

class One { public: int x ; }; class Wrapper { public: Wrapper(CString csText):mcsText(csText) { CString csTempText; csTempText.Format("Wrapper constructor :: %s\n", mcsText); OutputDebugString(csTempText); } ~Wrapper() { CString csTempText; csTempText.Format("Wrapper destructor :: %s\n", mcsText); OutputDebugString(csTempText); } CString mcsText; }; class Test { public: void notifyError() { try { int x = 10; } catch(...) {} } void OnRecvBuffer() { try { Wrapper a("AddRef"); One* p = NULL; p->x = 10; } catch(...) { notifyError(); } } }; int main() { Test* pTest = new Test; pTest->OnRecvBuffer(); OutputDebugString("Test"); } 

I compiled this code using the VC6 SP5 compiler, and the output is "Wrapper constructor :: AddRef !!!" (i.e., the destructor of the wrapper object that was constructed on the stack is not called. Is this the expected behavior? Or is it a bug with the VC compiler? Can I use some compiler flags so that the stack is rotated in this case?

+4
source share
4 answers

If you want to use SEH, you must use the _set_se_translator function and / EHa compiler.

+4
source

The C ++ standard gives nothing to work with Undefined Behavior. Even if MS does. This is a specific platform - so be careful. Some floating point exceptions refer to Win32 exceptions that you can try to catch with _set_se_translator() . The problem is that you can catch Win32 exceptions, but then your stack will not spin up properly. At least that's not what you can put your life on. What is the futility of the exercise.

Update: The exception is intentionally checked for stack expansion. The question is why the Wrapper class destructor is not called. - Naven

If so, do not do this. There are better ways to throw exceptions than through Undefined Behavior.

eg:

 void OnRecvBuffer() { try { Wrapper a("AddRef"); throw 42; // this'll throw an exception without invoking UB } catch(...) { notifyError(); } } 

You cannot dereference a NULL pointer. You invoke Undefined Behavior here:

 One* p = NULL; p->x = 10; 

After this line, all bets are disabled, and you could have killed all of us;)

p is a pointer to a One object. It must contain the address of the One object. You initialized it to 0 - the object has no address 0. 0 is not a valid address for any object (this is confirmed by the standard).

+7
source

Since a regular C ++ exception does not handle such an exception, you should use SEH, which knows nothing about the application and does not relax.

+2
source

This behavior is undefined:

 One* p = NULL; p->x = 10; 

At this point, the application can break freely without unwinding the stack.
If you want to test stack unwinding, replace it with:

  throw 42; // Life the Universe and Everything thrown away 

You do not have to dynamically allocate all of your objects, this is C ++, not Java!

 int main() { Test pTest; // Note the lack of new! pTest.OnRecvBuffer(); OutputDebugString("Test"); } 
0
source

All Articles