Handle C++ exception and structured exception together

G

George2

Hello everyone,


I am learning set_se_translator, and there are some good resources
about how to translate structured exception into C++ exception, like,

http://www.codeproject.com/KB/cpp/seexception.aspx

1.

What makes me confused is, when we are talking about translate, it
means both structured exception and C++ exception may occur in a C++
program, right?

2.

But from build option, we can select either /EHa or /EHsc, means we
can only select one type of exception, either asynchronous
(structured) or synchronous (C++ exception).

(1) and (2) are conflict?


thanks in advance,
George
 
A

anon

George2 said:
Hello everyone,


I am learning set_se_translator, and there are some good resources
about how to translate structured exception into C++ exception, like,

http://www.codeproject.com/KB/cpp/seexception.aspx

LOL
this code looks like coming from a clown:

catch(CSeException *e)
{
e->ReportError(MB_OK | MB_ICONSTOP);
e->Delete();
}

Wondering what they do in Delete() method. Hope not "delete this"

BTW http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.7 is
missing that the best way is to catch const reference
 
P

Pavel

George2 said:
Hello everyone,


I am learning set_se_translator, and there are some good resources
about how to translate structured exception into C++ exception, like,

http://www.codeproject.com/KB/cpp/seexception.aspx

1.

What makes me confused is, when we are talking about translate, it
means both structured exception and C++ exception may occur in a C++
program, right?

2.

But from build option, we can select either /EHa or /EHsc, means we
can only select one type of exception, either asynchronous
(structured) or synchronous (C++ exception).

(1) and (2) are conflict?


thanks in advance,
George
My understanding is that you need to use /EHsc, because your code will
catch C++ exceptions; the code that throws structured exceptions has
already been compiled into the libraries your code uses. Did not try it
myself though.

-Pavel
 
P

Pavel

anon said:
LOL
this code looks like coming from a clown:

catch(CSeException *e)
{
e->ReportError(MB_OK | MB_ICONSTOP);
e->Delete();
}

Wondering what they do in Delete() method. Hope not "delete this"

I thought "delete this" was not bad-bad, although certainly not ideal.
Sometimes there is no good alternative to at least indirect "delete
this" or its equivalent ... or I simply do not know one. Do you?
 
A

Alf P. Steinbach

* Pavel:
I thought "delete this" was not bad-bad, although certainly not ideal.
Sometimes there is no good alternative to at least indirect "delete
this" or its equivalent ... or I simply do not know one. Do you?

The problem is mostly that with an exception there's no designated
"owner" that's responsible for deleting. And with a catch(...) you have
a memory leak. The code above is based on MFC exceptions, which were a
pre-standard hack to use exceptions in a language implementation that
didn't support exceptions.

Cheers, & hth.,

- Alf
 
P

Pavel

Pavel said:
...

My understanding is that you need to use /EHsc, because your code will
catch C++ exceptions; the code that throws structured exceptions has
already been compiled into the libraries your code uses. Did not try it
myself though.

-Pavel
Sorry, my gut feeling was wrong, this time documentation says otherwise:
Use /EHa instead of /EHsc when using _set_se_translator.
see http://msdn2.microsoft.com/en-us/library/5z4bw5h5(VS.71).aspx

-Pavel
 
P

Pavel

Alf said:
* Pavel:

The problem is mostly that with an exception there's no designated
"owner" that's responsible for deleting. And with a catch(...) you have
a memory leak. The code above is based on MFC exceptions, which were a
pre-standard hack to use exceptions in a language implementation that
didn't support exceptions.

Cheers, & hth.,

- Alf
I agree, in general catch(...) does not work for throwing pointers; but
in the example in question the structured exceptions are all inherited
from CSeException so they can be safely caught and deleted if needed.
Structured exceptions targeted C language, with no automatic stack
unwinding, kind of glorified setjmp()/longjmp() so throwing pointers and
deleting memory in the handler seems to be a more or less precise
mapping of the concept into the standard C++ syntax.

I believe the "clown" pan was aimed at "delete this" idea though.

-Pavel
 
A

Alf P. Steinbach

* Pavel:
I agree, in general catch(...) does not work for throwing pointers; but
in the example in question the structured exceptions are all inherited
from CSeException so they can be safely caught and deleted if needed.
Structured exceptions targeted C language, with no automatic stack
unwinding, kind of glorified setjmp()/longjmp() so throwing pointers and
deleting memory in the handler seems to be a more or less precise
mapping of the concept into the standard C++ syntax.

I believe the "clown" pan was aimed at "delete this" idea though.

* C++: I believe the "clown" comment was aimed at throwing pointers to
dynamically allocated objects. It's a recipe for disaster, because of
the lack of designated owner and possibility of "catch(...)". Using
"delete this", on the other hand, is a normal way to do destruction in
many situations, nothing wrong with that, although it is a power tool
that can be dangerous in untrained hands.

* Windows: structured exception handling (SEH) is an operation system
API way to communicate failure that targets no specific language, but
does require language support. Most of it is undocumented. As I recall
Matt Pietrik (not sure of speling) wrote a series of articles going into
depth of the undocumented aspects, including typical language support.

* MFC exceptions (MFC is an old C++ GUI framework from Microsoft):
throwing pointers had, as far as I know, nothing to do with SEH, and
these exceptions were not targeted at C, since MFC was and is a C++
class framework. Rather, it probably had to do with this exception
handling being implemented via macros and nifty hacking, before C++
exception handling became available. Keep in mind that MFC predates the
C++ standard, and that C++ exception handling wasn't frozen until late
in the standardization process.

The pre-standard macro way (example lifted from [1]):

TRY
{
// Do something to throw an exception.
AfxThrowUserException();
}
CATCH(CException, e)
{
if (m_bPassExceptionsUp)
THROW_LAST();

if (m_bReturnFromThisFunction)
return;

// Not necessary to delete the exception e.
}
END_CATCH

Using standard C++ exception handling the cleanup that was hidden in the
macros must be done manually:

try
{
// Do something to throw an exception.
AfxThrowUserException();
}
catch(CException* e)
{
if (m_bPassExceptionsUp)
throw;

if (m_bThrowDifferentException)
{
e->Delete();
throw new CMyOtherException;
}

if (m_bReturnFromThisFunction)
{
e->Delete();
return;
}

e->Delete();
}

Of course, this mess is on its own a good reason not to use MFC... ;-)

Cheers, & hth.,

- Alf


Notes:
[1] <url: http://msdn2.microsoft.com/en-us/library/19z28s5c.aspx>
 
P

Pavel

anon said:
Sure, and the synposis of the answer to this FAQ is (quoting):
"As long as you're careful, it's OK for an object to commit suicide
(delete this)."
Do you have an example where "delete this" would be good? Or at least
not bad?
virtual Delete() or destroy() function is one of the OK ways to free the
object's memory (after freeing all other resources owned by the object,
if any) when the object knows how to free the memory it occupies in most
general case. When the memory is to be freed via delete, the function
has to call delete.

The technique has its pros and contras (IMHO mostly pros) when compared
with the alternatives I know. Do you know a clearly superior alternative?

-Pavel
 
P

Pavel

....
* C++: I believe the "clown" comment was aimed at throwing pointers to
dynamically allocated objects.
I disagree. "delete this" fragment was brought up by the commenter (see
above), it was not in the original post.

It's a recipe for disaster, because of
the lack of designated owner and possibility of "catch(...)". U
In general, it is a recipe for a memory leak (whether a memory leak is
always and patently a disaster is a different matter). In particular,
when only structured exceptions (thrown by the underlying C API we do
not control) are processed by throwing a pointer to an exception and all
such exceptions have a common base class (in the example, CSeException),
it seems acceptable to me (and will not create a memory leak). I am just
trying to keep in mind the original problem: processing Windows
sructured exceptions in C++ code.
"delete this", on the other hand, is a normal way to do destruction in
many situations, nothing wrong with that, although it is a power tool
that can be dangerous in untrained hands.
Completely agree.
* Windows: structured exception handling (SEH) is an operation system
API way to communicate failure that targets no specific language, but
does require language support. Most of it is undocumented. As I recall
Matt Pietrik (not sure of speling) wrote a series of articles going into
depth of the undocumented aspects, including typical language support.
Well, it is documented in the enough details to catch them in C. "No
specific language" is correct for the exception client but not for the
code that raises exception (it is C API, after all).

Language support (beyond setjmp()/longjmp() support which would
introduce platform dependency anyway, by C standard) was not really
required to solve the problem, it was just usual old Microsoft's way of
presenting their facilities in the most nonstandard way possible.
* MFC exceptions (MFC is an old C++ GUI framework from Microsoft):
throwing pointers had, as far as I know, nothing to do with SEH, and
these exceptions were not targeted at C, since MFC was and is a C++
class framework.
Well that's where I would partly disagree. What you are saying is a
possibility but why exactly Microsoft introduced this "MFC standard way"
of throwing will probably stay unknown forever. Theoretically it is
possible it did not have anything to do with SEH but it is obvious to me
that unconditionally leaving the destruction of the exception
information up to the exception handler is so consistent with the
structured exceptions and old C ways (again, I heard your "no specific
language" but ? was the primary API target and implementation language
(with some assembler) so I would not bet much on that.

But it is all misses the point (almost). The reason why I mentioned the
MFC exception is because the code in the question took MFC base
exception to handle Windows structured exceptions (even though the did
not have to do it):

class CSeException : public CException
{
....

and then the followed the regular MFC practice of throwing the pointers.
The resulting code and suggested framework seem reasonably save to me as
long as the users will use MFC conventions consistently (which they will
have trouble not to do anyway as the solution introduces dependencies on
MFC).

....
Of course, this mess is on its own a good reason not to use MFC... ;-)
Agree, I never liked MFC myself. Even now I use C API on Windows --
"When in Rome .." -- and AFAIK "Romans" do not use MFC for their killer
apps -- or maybe they do now but before they did not.

-Pavel
 
A

Alf P. Steinbach

* Pavel:
...
I disagree. "delete this" fragment was brought up by the commenter (see
above), it was not in the original post.

It's a recipe for disaster, because of
In general, it is a recipe for a memory leak (whether a memory leak is
always and patently a disaster is a different matter).

It can easily lead to memory leaks, yes, and it can also easily lead to
double destruction. Both are generally disasters. Although possibly
not immediate disasters in the sense of an immediate program crash.

In particular,
when only structured exceptions (thrown by the underlying C API we do
not control) are processed by throwing a pointer to an exception and all
such exceptions have a common base class (in the example, CSeException),
it seems acceptable to me (and will not create a memory leak).

First, since the code is using MFC exceptions it's not only SEH
exceptions that are handled that way.

Second, the conclusion "and will not create a memory leak" does not follow.

On the contrary, since SEH exceptions can be asynchronous and can occur
at any point (e.g. for dereferencing a nullpointer), translating them to
C++ throwing of pointer to dynamically allocated exception object is
very likely to result in a memory leak, unless all the code is under
your control -- and even then...

I am just
trying to keep in mind the original problem: processing Windows
sructured exceptions in C++ code.

Not a big deal, except it's necessarily C++ implementation-specific, in
particular possibly requiring special compiler switches.


Completely agree.

Well, it is documented in the enough details to catch them in C.

No, the SEH documentation is for Microsoft's C and C++ language extensions.

"No
specific language" is correct for the exception client but not for the
code that raises exception (it is C API, after all).

No, it's not a C API.

The documented language extensions are for C and C++. However, it's not
documented how they work together with the (operating system) API, i.e.
how these extensions are implemented or what you'd do without them. At
least, it didn't use to be documented, and I haven't checked lately.

However, that's largely off-topic in clc++.

Language support (beyond setjmp()/longjmp() support which would
introduce platform dependency anyway, by C standard) was not really
required to solve the problem, it was just usual old Microsoft's way of
presenting their facilities in the most nonstandard way possible.

Well that's where I would partly disagree. What you are saying is a
possibility but why exactly Microsoft introduced this "MFC standard way"
of throwing will probably stay unknown forever. Theoretically it is
possible it did not have anything to do with SEH but it is obvious to me
that unconditionally leaving the destruction of the exception
information up to the exception handler is so consistent with the
structured exceptions and old C ways (again, I heard your "no specific
language" but ? was the primary API target and implementation language
(with some assembler) so I would not bet much on that.

But it is all misses the point (almost). The reason why I mentioned the
MFC exception is because the code in the question took MFC base
exception to handle Windows structured exceptions (even though the did
not have to do it):

class CSeException : public CException
{
...

and then the followed the regular MFC practice of throwing the pointers.
The resulting code and suggested framework seem reasonably save to me as
long as the users will use MFC conventions consistently (which they will
have trouble not to do anyway as the solution introduces dependencies on
MFC).

Following MFC (cleanup) conventions consistently is difficult because
they are conventions that must be implemented manually, as opposed to
the automatic cleanup functionality of standard C++ exceptions.

...
Agree, I never liked MFC myself. Even now I use C API on Windows --
"When in Rome .." -- and AFAIK "Romans" do not use MFC for their killer
apps -- or maybe they do now but before they did not.

AFAIK the Romans use WTL.


Cheers, & hth.,

- Alf
 
P

Pavel

Alf said:
It can easily lead to memory leaks, yes, and it can also easily lead to
double destruction. Both are generally disasters. Although possibly
not immediate disasters in the sense of an immediate program crash.
Please.. we are talking about a concrete facility as per the original
question. They throw pointers and delete them in handlers. Apparently
they cannot do it in (...) handler (which would create a memory leak but
I refuse to see how it, per se, can lead to a double destruction) but
they do not try to do it and they do not have to do it. The MFC style:
throw CException or its derived classes reasonably handles the issue.
What disasters are we hinting at here?
First, since the code is using MFC exceptions it's not only SEH
exceptions that are handled that way.
Maybe yes, maybe not, we don't have a way to say for sure but is it
relevant to the subject?
Second, the conclusion "and will not create a memory leak" does not follow.
Ok "does not have to create memory leak" is what I meant to say. Of
course it does not follow because we do not have the whole code to see
(and it is the only way to say for sure for any source code and very
expensive way at that). My only point is that they have enough control
with this approach to avoid memory leaks. With (...) handlers they would
not have such facility -- that is all I say.

On the contrary, since SEH exceptions can be asynchronous and can occur
at any point (e.g. for dereferencing a nullpointer), translating them to
C++ throwing of pointer to dynamically allocated exception object is
very likely to result in a memory leak, unless all the code is under
your control -- and even then...



Not a big deal, except it's necessarily C++ implementation-specific, in
particular possibly requiring special compiler switches.
Agreed that the question about the compiler switches was implementation
specific but we quickly switched to an issue of safe handling of the
resulting C++ exceptions which is IMHO C++ implementation-independent.
No, the SEH documentation is for Microsoft's C and C++ language extensions.
You can handle these exceptions in standard C way by registering a
callback in _set_se_translator function and translating into regular C++
exceptions in it. Not sure where a language extension comes into play here.
No, it's not a C API.
I mean "the code that raises an exception is C code and it does so by
using C function RaiseException()". Isn't it C API?
The documented language extensions are for C and C++. However, it's not
documented how they work together with the (operating system) API, i.e.
how these extensions are implemented or what you'd do without them. At
least, it didn't use to be documented, and I haven't checked lately.

However, that's largely off-topic in clc++.
Is it ok to discuss the advantages/drawbacks of different approaches of
adapting non-C++ into C++ here?
....
AFAIK the Romans use WTL.
Thanks for the hint -- I will definitely look into WTL. But I meant
"Windows " for Rome and "Windows developers in Microsoft" for Romans.
For example for Windows Explorer or Office -- they always used C API (or
used to do so), one reason being that the correspondent MFC classes
simply did not exist by the release time. I remember this was the case
when Windows 95 was released and List View and Tree View were first used
in its Explorer and this life cycle (feature->C API documentation for
the feature->MFC API->Fixing MFC API bugs absent in the feature which
more or less proves that the feature was not implemented with MFC) was
followed for at least some years after that.

Regards,
-Pavel
 
A

Alf P. Steinbach

* Pavel:
Please.. we are talking about a concrete facility as per the original
question. They throw pointers and delete them in handlers. Apparently
they cannot do it in (...) handler (which would create a memory leak but
I refuse to see how it, per se, can lead to a double destruction) but
they do not try to do it and they do not have to do it. The MFC style:
throw CException or its derived classes reasonably handles the issue.
What disasters are we hinting at here?

I think it's as concrete as can be described with words, no hinting.

Double destruction example would just be example of destroying twice,
which is easy to do when using manual destruction instead of RAII,
especially in code where that destruction has to be redundantly repeated
(as is the case with MFC exception handler code).

Memory leak + disaster example code:

void throwX( char const s[] ) { throw std::runtime_error( s ); }

struct Base()
{
virtual ~Base() {}
virtual void foo() = 0;
void bar()
{
try { foo(); } catch( ... ) { throwX( "Base::bar()" ); }
}
};

struct SillyDerived: Base
{
void foo() { int* p = 0; *p = 666; }
};

Now with general SEH -> C++ exception translation enabled, and that SEH
nullpointer exception translated to a C++ throw of pointer to
dynamically allocated object, a call to bar() leaks memory, and much
worse, in the general case where a nullpointer exception indicates
something gone horribly awry, is likely to leave the program in an
unstable state (memory corruption, invalid assumptions) => disaster.


Cheers, & hth.,

- Alf
 
P

Pavel

Alf said:
I think it's as concrete as can be described with words, no hinting.

Double destruction example would just be example of destroying twice,
which is easy to do when using manual destruction instead of RAII,
especially in code where that destruction has to be redundantly repeated
(as is the case with MFC exception handler code).

Memory leak + disaster example code:

void throwX( char const s[] ) { throw std::runtime_error( s ); }

struct Base()
{
virtual ~Base() {}
virtual void foo() = 0;
void bar()
{
try { foo(); } catch( ... ) { throwX( "Base::bar()" ); }
}
};

struct SillyDerived: Base
{
void foo() { int* p = 0; *p = 666; }
};

Now with general SEH -> C++ exception translation enabled, and that SEH
nullpointer exception translated to a C++ throw of pointer to
dynamically allocated object, a call to bar() leaks memory, and much
worse, in the general case where a nullpointer exception indicates
something gone horribly awry, is likely to leave the program in an
unstable state (memory corruption, invalid assumptions) => disaster.
I agree this example won't work.. but why would anybody use catch(...)
for structured exception if the point is to catch CseException or
CException?

See, my understanding of the idea of the article is this:

1. Someone has a WIN32 C library that can throw SHE (or, also, WIN32
itself can do it) and wants to expose these facilities from his C++
library. Say, that C WIN32 C library has a function

void cf(); /* can "throw" SHE */

2. That someone writes a C++ library, including the function, say:

void cppf() throw(CseException *); // I know MSVC++ does not really
// support throw(), not in 2005, anyway, but let's pretend it does..
// maybe it does 2008 or will later.
// And anyway, the interface is useful just
// to show that the function can throw CseException

The library's initialization code will set up the function translating
SHE to C++ exception

3. Then, any sensible programmer who uses the C++ library would write
the client code along these lines:

try {
....
cppf(); // maybe indirectly
....
} catch(CseException *exPtr) {
... // process exception
// Any person familiar with MFC "style" of exception
// pointers ownership,
// will manage the exPtr life style accordingly
}

It is certainly more error prone than RAII would be; on the other hand,
RAII is a very useful but not the only useful way of resource
management.. otherwise why would we need shared_ptr(), garbage
collectors and similar machinery. For example, if one wants to post the
*exPtr or the pointer to _EXCEPTION_POINTERS that it contains onto to a
queue from where a separate task would process all the exceptions
asynchronously, RAII will not help.

BTW, some Microsoft's apparently strange habits in using C++ become
easier to come to terms with if one keeps in mind their strong
background in "asynchronous message-driven" programming paradigm. When
this paradigm is used, the message sometimes originates in one "piece"
of the program (whether the piece it is a thread, a process or a module)
and is to be processed and destroyed in another. It is not always
possible to use RAII in such code.

Regards
-Pavel
 
A

Alf P. Steinbach

* Pavel:
Alf said:
I think it's as concrete as can be described with words, no hinting.

Double destruction example would just be example of destroying twice,
which is easy to do when using manual destruction instead of RAII,
especially in code where that destruction has to be redundantly
repeated (as is the case with MFC exception handler code).

Memory leak + disaster example code:

void throwX( char const s[] ) { throw std::runtime_error( s ); }

struct Base()
{
virtual ~Base() {}
virtual void foo() = 0;
void bar()
{
try { foo(); } catch( ... ) { throwX( "Base::bar()" ); }
}
};

struct SillyDerived: Base
{
void foo() { int* p = 0; *p = 666; }
};

Now with general SEH -> C++ exception translation enabled, and that
SEH nullpointer exception translated to a C++ throw of pointer to
dynamically allocated object, a call to bar() leaks memory, and much
worse, in the general case where a nullpointer exception indicates
something gone horribly awry, is likely to leave the program in an
unstable state (memory corruption, invalid assumptions) => disaster.

I agree this example won't work.. but why would anybody use catch(...)
for structured exception if the point is to catch CseException or
CException?

Especially with virtual functions, but also with function pointers and
templated functionality, at the point where you write the catch(...) you
don't know what code is executed, what exceptions can occur, and you
don't write catch(...) in order to use a language extensions that makes
this catch SEH exceptions, but in order to catch any /C++/ exception.

And in particular, that catch(...) can reside in existing years old code
that calls your new code.

E.g. Base above might be a SuperDuper library class from Microsoft
(quickly searching through the MS code on my machine, however, I found
only 1 instance of this pattern), and SillyDerived your new shiny class,
throwing SEH exception by accident.

Cheers, & hth.,

- Alf
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,228
Members
46,818
Latest member
SapanaCarpetStudio

Latest Threads

Top