T.E.D.
T.E.D.

Reputation: 44804

Windows SEH and memory management

I'm writing some code that handles Windows structured exceptions (in my case using _set_se_translator() to convert them to C++ exceptions).

The thing that is worrying me is the extensive use of pointers in the exception information I get passed when an exception occurrs. I get passed a pointer to an _EXCEPTION_POINTERS struct. It contains pointers to two other structs, one of which possibly contains another pointer field that makes that object basically a linked-list.

Where does the memory behind all these pointers get allocated? Who is responsible for deallocating it? If it isn't me, how long can I count on the data being valid and how do I avoid leaks?

My se translator routine currently looks like this:

void se_translator(unsigned int exception_code, struct _EXCEPTION_POINTERS* exception_information) {
    _clearfp();
    throw se_exception(exception_code, exception_information);
};

And the worry here is either that all the data pointed to within exception_information will be out of scope inside my catches, or that they will all leak somehow.

If there's some documentation that discusses this, I'd like to be pointed to it.

Upvotes: 3

Views: 800

Answers (1)

Remus Rusanu
Remus Rusanu

Reputation: 294407

Stack. The exception record is pushed on the stack before the exception is raised. See A Crash Course on the Depths of Win32™ Structured Exception Handling. EXCEPTION_POINTERS is a Visual C++ specific extension to the SEH's EXCEPTION_REGISTRATION:

Immediately below its extended EXCEPTION_REGISTRATION structure, Visual C++ pushes two additional values. In the DWORD immediately below, it reserves space for a pointer to an EXCEPTION_POINTERS structure (a standard Win32 structure). This is the pointer returned when you call the GetExceptionInformation API.

In fact SEH uses only stack structures because under exception conditions is the only most reliable memory allocator. Is not foul-proof (if there is no stack space for the exception record, your process vanishes w/o a trace) but is the best there is.

 throw se_exception(exception_code, exception_information);

exception_information will be out of scope inside my catch

No, it won't. Your stack will look something like this:

somefunction_x::`catch block
DispatchException
RaiseException 
<- exception record is here ->
frame that triggered the SEH raise (c++ throw, AV, stack overflow etc)
caller
somefunction_x
caller
threadentrypoint

But what you're doing is highly unusual. Normally translators transform the non c++ exceptions like AV (ExceptionCode is EXCEPTION_ACCESS_VIOLATION) into a specific c++ exception, eg. they inspect the exception record ExceptionCode and raise appropriate C++ typed exception.

Upvotes: 4

Related Questions