Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

TRanslating SEH to C++ exceptions

336 views
Skip to first unread message

Martin Aupperle

unread,
Feb 23, 2001, 11:09:51 AM2/23/01
to
Hello,

I have used _set_se_translator to map Win32-Structured Exceptions to
standard C++ exceptions. Works fine, but I loose the context
information. For Example, when I have an access violation, the
VC-debugger can position to line and file where the situation occured.
With the translator installed I cannot get that info.

Any ideas?

Martin

------------------------------------------------
Martin Aupperle
MikeAlpha@NoSpam_csi.com
(remove NoSpam_)
------------------------------------------------

Todor Slavov

unread,
Feb 25, 2001, 11:18:17 AM2/25/01
to
On Fri, 23 Feb 2001 16:09:51 GMT, MikeAlpha@NoSpam_csi.com (Martin
Aupperle) wrote:

> Hello,
>
> I have used _set_se_translator to map Win32-Structured Exceptions to
> standard C++ exceptions. Works fine, but I loose the context
> information. For Example, when I have an access violation, the
> VC-debugger can position to line and file where the situation occured.
> With the translator installed I cannot get that info.
>
> Any ideas?
>

I'm not sure what exactly you want.

Do you want to handle converted SEs?

Just throw your exception type from the translator function and make
sure that all compilation units that use this "feature" are compiled
with /EHa. If you don't use this option the compiler may decide to
remove the entire try/catch block. For more explanation search for
posts from Doug Harrison and content "_set_se_translator". Actualy I'm
surprised that Doug hasn't aswered you already. SE translation seems
to be one of his favorite topics :-)

Even then the SE translation is not completely reliable. E.g. with the
following code:

/* #include's omitted for brevity */
struct X {
X() {}
~X() { std::cerr << "X::~X()" << std::endl; }
};

void foo()
{
X x;
*(int*)0 = 1;
}

static void _cdecl se_error_func(UINT u, EXCEPTION_POINTERS*)
{
std::cerr << "In se_error_func" << std::endl;
throw u;
}

int main()
{
_set_se_translator(se_error_func);
try {
foo();
}
catch(UINT u) {
std::cerr << "SEHCode: " << std::hex << u << std::endl;
}
return 0;
}

I would expect a call to X destructor, and indeed in the debug build
the output is:
In se_error_func
X::~X()
SEHCode: c0000005

In the release build I get only:
In se_error_func
SEHCode: c0000005

Looks like there is no stack unwinding at all. Quite dangerous. In
fact, even if I don't use _set_se_translator and catch AVs in
catch(...) there is still no destructor call in release build.

In my opinion the only reliable way to deal with SEs is __try/__catch.
There are too many gotchas with the translation.

Now, on the bright side, if you want to prevent SEs from being catched
by catch(...) you can use this translator:
void _cdecl se_always_fail_func(UINT, EXCEPTION_POINTERS*)
{throw;}
It has the effect of dropping you into the offending line when
debugging, and nice big "Access Violation" message box otherwise.
There was an interesting thread on comp.lang.c++.moderated titled
"Visual Studio.net: bah humbug" where this workarround was posted.
Boost list archives also have some info on this topic.

Also keep in mind that translator function is per thread. From the
_set_se_translator docs:
"In a multithreaded environment, translator functions are maintained
separately for each thread. Each new thread needs to install its own
translator function. Thus, each thread is in charge of its own
translation handling."

Todor

Martin Aupperle

unread,
Feb 28, 2001, 10:33:59 AM2/28/01
to
On Sun, 25 Feb 2001 16:18:17 GMT, td...@hotmail.com (Todor Slavov)
wrote:

>On Fri, 23 Feb 2001 16:09:51 GMT, MikeAlpha@NoSpam_csi.com (Martin
>Aupperle) wrote:
>
>> Hello,
>>
>> I have used _set_se_translator to map Win32-Structured Exceptions to
>> standard C++ exceptions. Works fine, but I loose the context
>> information. For Example, when I have an access violation, the
>> VC-debugger can position to line and file where the situation occured.
>> With the translator installed I cannot get that info.
>>
>> Any ideas?
>>
>
>I'm not sure what exactly you want.
>

I want in my C++ exception the ability to know in which statement the
error occured. For example, when I have a access violation, I want to
see in my log file (or trace statements) the file name and line
number. Since the debugger can jump to the offending line, that
context information should be somewhere. Where can I get it from to
put it into my C++ exception?

[how to translate snipped - the translation is no problem]

I tried something similar this with my Windows code and found out that
the dtor is NEVER called! Clearly a bug. I will have a memory leak
here in some situations. But since OS-Exceptions should be rare, I can
live with that. When possible I changed

try
{
X x;
...
}
catch ....

to

X x;
try
{
...
}
catch ...

but this is not always possible and should be considered a hack.

>Looks like there is no stack unwinding at all. Quite dangerous. In
>fact, even if I don't use _set_se_translator and catch AVs in
>catch(...) there is still no destructor call in release build.
>

This works in my case. Standard C++ exceptions work correctly. Did you
remove the null pointer dereferencing statement also? If not, it will
trigger a SE which will not unwind the stack unless in __try/__catch.

>In my opinion the only reliable way to deal with SEs is __try/__catch.
>There are too many gotchas with the translation.
>
>Now, on the bright side, if you want to prevent SEs from being catched
>by catch(...) you can use this translator:
>void _cdecl se_always_fail_func(UINT, EXCEPTION_POINTERS*)
> {throw;}
>It has the effect of dropping you into the offending line when
>debugging, and nice big "Access Violation" message box otherwise.

How come this works? A throw with no arguments is allowed only in a
catch handler!. The only solution can be that the translator function
is called from such a catch handler. But what type of exception is
being active at that time? I can not even look at the stack trace (all
asm!).


>There was an interesting thread on comp.lang.c++.moderated titled
>"Visual Studio.net: bah humbug" where this workarround was posted.
>Boost list archives also have some info on this topic.
>

Indeed interesting!

Martin Aupperle

unread,
Mar 5, 2001, 3:18:29 PM3/5/01
to
>"Martin Aupperle" <MikeAlpha@NoSpam_csi.com> wrote in message
>news:3a9ce534....@news.nikoma.de...

>> I want in my C++ exception the ability to know in which statement the
>> error occured. For example, when I have a access violation, I want to
>> see in my log file (or trace statements) the file name and line
>> number. Since the debugger can jump to the offending line, that
>> context information should be somewhere. Where can I get it from to
>> put it into my C++ exception?
>
>It is fairly easy to determine the address where the exception occurred in
>the translator. VirtualQuery() can be used to determine the base address of
>the module that contains an address and GetModuleFileName() can turn a base
>address into the name of a DLL or executable.
>
>The image helper library includes a set of functions - SymInitialize(),
>SymGetModuleInfo(), SymGetSymFromAddr() among them - that should be able to
>manipulate the debug info. I would guess that you could use this library to
>translate addresses into modules and lines.
>
Yes I can make a stack trace with the help of the image helper
library. I used the code from Matt PIetrek in "UNder the hood" from an
early MS Journal. I easily can print out the function where the Access
Violation occurs, and an offset into that function, too. But not the
statement of the source code. That'S what I want. Should'nt it be
possible to get the line number from the offset? Debuggers do it,
too!.

>I wonder, though, if there are issues calling this library from inside an
>exception handler?
>
No. Why should it?

>In any event, I've put together a C++ class that can be used to translate
>structured exceptions to C++ exceptions. The class includes a toString()
>function ( suggested by Java's function of the same name ) to display the
>exception, and the address, module and offset where it occurred.

Nothing new - but thank you anyway!

>I wimped
>out at displaying the line number and call stack.
>

The line number part would be the intersting thing. I also have code
for printing the call stack.

Martin

William DePalo [MVP]

unread,
Mar 9, 2001, 5:50:00 PM3/9/01
to
"Martin Aupperle" <MikeAlpha@NoSpam_csi.com> wrote in message
news:3aa3e6da...@news.nikoma.de...

> I easily can print out the function where the Access
> Violation occurs, and an offset into that function, too. But not the
> statement of the source code. That'S what I want. Should'nt it be
> possible to get the line number from the offset? Debuggers do it,
> too!.

Yes. Check the docs for SymGetLineFromAddr(). It is one of the functions in
the image helper library.

Regards,
Will

Martin Aupperle

unread,
Mar 19, 2001, 11:32:55 AM3/19/01
to

Thanks!

Although it does not work on my machine, I can find its documentation
on MSDN. Hopefully its a matter of time to get it working.

0 new messages