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

using catch(...) in VC++ is cause of unreliable behavior.

3 views
Skip to first unread message

Vladimir Petter

unread,
Sep 16, 2003, 8:42:09 PM9/16/03
to
Hi,
 
I am wondering why Microsoft has decided to catch all exceptions
(including all SEH exceptions) in the C++ catch(...) block?
I think this feature compromise catch(...) and makes it dangerous to use.
 
There is my rationale why it should NOT be done. Correct me if I am wrong.
 
1. In the "catch(...)" you can not distinguish if you couched C++ or other kind of
SEH exception. Further I'll be talking only about caching NON C++
exceptions in the "catch(...)" (Catching all C++exceptions is not a problem - that was
the original design for that block).
 
2. Throwing a new exception from the "catch(...)" makes it impossible to figure
out what was the original exception. Consider following example:
 
try{
  int *p=NULL;
  *p = 0;                    #1
 } catch (...) {
  int *d=NULL;
  *d = 0;                    #2
 }
You will see that there is an exception in the #2, but you would not be able to figure out
how did you get there in the first place, that is especially dangerous because #1 may be
changed (for demo purpose :-) ) to put process into an invalid state (corrupt heap/stack etc).
This leads us to item (3).
 
3. After you've got to the catch(...) you do not know if it is caused by C++
throw of a SEH exception so you cannot make any assumptions regarding
stability of the process. No matter how good is code quality inside this block it still
can fail.
 
4. C++ does not have "finally" block (like Java) so I have to ether use destructors or
use something like
} catch (...) {
    //free resources
    throw;
}
to emulate it. As explained above catching SEH makes this technique unreliable because
I cannot assume that I can safely free resource no mater how accurate/paranoid I am in
my coding style (for example stack was corrupted, we got access violation and now in
the catch(...) we are trying to free another piece of memory).
Using destructors to free resources does not make things better because once destructor
throws exception during stack unwinding (Same scenario as above. The exception could be
thrown not by design, but because process was corrupted) the program will be terminated.
 
5. Even if program is not corrupted there is no guaranty that destructors will be called unless you are
using /EHa (asynchronous exception handling, which is not the default one ).
 
What I would prefer is to have program crash once it got corrupted rather that have it
running for a while and have it crashed later on in some unpredictable place. In this
way program behavior would be more deterministic and it would be much easier to
study it using a postmortem debugger.
 
Is it achievable in VC++?
 
There is one solution that is error prone (full version of program you can see at the end of this mail)
 Use _set_se_translator may be used to solve the problem at some extent.
It allows to filter SEH exceptions to a dedicated catch block and throw them forward. This technique has
several issues that makes it hard to use:
 
1. Every catch(...) block must have complimentary must have catch(SEH_exception &) block. If somebody
forgot follow this rule the exception will be eaten.
2. _set_se_translator must be called for each thread. This makes it hard to use especially if not all threads
was created explicitly (like DCOM MTA threads pool, etc.)
3. You still have to use /EHa in all modules.
 
This three problems already too much to consider _set_se_translator as a reliable solution.
 
I think the best would be clearly split SEH and C++ exceptions and, at least, never let SEH exceptions
be couched by catch(...) block (catching C++ exceptions by __except block still may have some value).
 
Thanks,
Vladimir.
 
 
 
 
#include <windows.h>
#include "eh.h"
#include "exception"
#include "iostream"
#include "process.h"
 
typedef void (*se_translaor_t)(unsigned int code, PEXCEPTION_POINTERS ex);
 
struct SEH_exception{};
 
template<class T = SEH_exception>
class scopped_se_translator {
public:
 explicit scopped_se_translator(se_translaor_t new_se_translator=NULL) : _previose_se_translator(NULL) {
  se_translaor_t se_translator = new_se_translator ? new_se_translator : default_se_translator;
  _previose_se_translator = _set_se_translator(se_translator);
  std::cout << "scopped_se_translator was set to " << new_se_translator << std::endl;
  std::cout.flush();
 }
 
 ~scopped_se_translator() {
  restore_translator();
 }
 
 void restore_translator() {
   _set_se_translator(_previose_se_translator);
   std::cout << "scopped_se_translator was reset to " << _previose_se_translator << std::endl;
   std::cout.flush();
 }
 
private:
 static void default_se_translator(unsigned int code, PEXCEPTION_POINTERS ex) {
    std::cout << "default_se_translator throw SEH_exception, SEH code=" << code << std::endl;
    std::cout.flush();
    throw T();
 }
 
 se_translaor_t _previose_se_translator;
};
 
 
 
class bogus_class {
public:
 
void assync_exception() {
  try{
   scopped_se_translator<> translator;
   char *bogus_pointer = NULL;
            *bogus_pointer = 'a';
  } catch (std::exception &ex) {
   std::cout << "bogus_class::assync_exception catched " << ex.what() << std::endl;
   std::cout.flush();
  } catch (SEH_exception &) {
   std::cout << "bogus_class::assync_exception catched bogus_class::SEH_exception" << std::endl;
   std::cout.flush();
   throw; //propagate SEH exceptions forward
  } catch (...) {
   std::cout << "bogus_class::assync_exception catched catch(...)" << std::endl;
   std::cout.flush();
  }
  std::cout << "assync_exception finished" << std::endl;
 }
 void sync_exception() {
  try{
   scopped_se_translator<> translator;
   throw 1;
  } catch (std::exception &ex) {
   std::cout << "bogus_class::sync_exception catched " << ex.what() << std::endl;
   std::cout.flush();
  } catch (SEH_exception &) {
   std::cout << "bogus_class::sync_exception catched bogus_class::SEH_exception" << std::endl;
   std::cout.flush();
   throw; //propagate SEH exceptions forward
  } catch (...) {
   std::cout << "bogus_class::sync_exception catched catch(...)" << std::endl;
   std::cout.flush();
  }
  std::cout << "sync_exception finished" << std::endl;
 }
};
 
 
int main(int argc, TCHAR* argv[]){
 try{
  scopped_se_translator<> translator;
  bogus_class c;
  c.assync_exception();
  //c.sync_exception();
 } catch (std::exception &ex) {
  std::cout << "main catched " << ex.what() << std::endl;
  std::cout.flush();
 } catch (SEH_exception &) {
  std::cout << "main catched SEH_exception " << std::endl;
  std::cout.flush();
  throw; //propagate SEH exceptions forward
 } catch (...) {
  std::cout << "main catched catch(...)" << std::endl;
  std::cout.flush();
 }
 std::cout << "main finished" << std::endl;
    return 0;
}
 

Vladimir Petter

unread,
Sep 16, 2003, 9:57:08 PM9/16/03
to
I have not seen that this topic was discussed in different articles many times, before
I posted. See:
As far as it was considered a bad feature for a long time is there any plans to change it or at least introduce some language extension
that would let figure out exception type/code?
like
 
try{
...
} catch (...) {
    if(is_cpp_exception()){
        ...
    } else {
        throw;
    }
}
 
All though this adds some ugliness to the code.
 
I am curies about that because I sow in several companies that people misusing catch(...).
It is error prone.
 
It would be especially interesting to hear an opinien from a Microsoft guy.
 
Vladimir.

Ronald Laeremans [MSFT]

unread,
Sep 16, 2003, 10:08:03 PM9/16/03
to
The current plan is for the next release not to catch SEH exceptions when
building /EHs (which is already likely broken depending on what the
optimizer decides to do) but to continue doing so when compiled /EHa.

Ronald Laeremans
Visual C++ team

"Vladimir Petter" <vla...@hotmail.com> wrote in message
news:%23QUdM9L...@tk2msftngp13.phx.gbl...

Vladimir Petter

unread,
Sep 16, 2003, 10:34:15 PM9/16/03
to
Thanks for your response,

Looking forward for the next release!

Vladimir.

"Ronald Laeremans [MSFT]" <ron...@online.microsoft.com> wrote in message
news:uxfmOCMf...@tk2msftngp13.phx.gbl...

Bruno van Dooren

unread,
Sep 17, 2003, 3:32:59 AM9/17/03
to
myabe a stupid question, but why are not all exceptions derived from
::exception?
I have always found it strange that you can throw any type as an exception.

kind regards,
Bruno.


Bo-Staffan Lankinen

unread,
Sep 17, 2003, 7:44:27 AM9/17/03
to
> The current plan is for the next release not to catch SEH exceptions when
> building /EHs (which is already likely broken depending on what the
> optimizer decides to do) but to continue doing so when compiled /EHa.
>
> Ronald Laeremans
> Visual C++ team

That is great news, thanks for the information. Will you be switching to
table based EH aswell?

Bo-Staffan


Hendrik Schober

unread,
Sep 17, 2003, 8:33:37 AM9/17/03
to
"Bruno van Dooren" <micr...@hotmail.com> wrote:
> myabe a stupid question, but why are not all exceptions derived from
> ::exception?
> I have always found it strange that you can throw any type as an exception.

Because the C++ standard gives you the freedom
to throw what you want. Of course, you don't
need to use that freedom.

> kind regards,
> Bruno.

Schobi

--
Spam...@gmx.de is never read
I'm Schobi at suespammers org

"And why should I know better by now/When I'm old enough not to?"
Beth Orton


Bruno van Dooren

unread,
Sep 17, 2003, 8:49:53 AM9/17/03
to

> Because the C++ standard gives you the freedom
> to throw what you want. Of course, you don't
> need to use that freedom.

the problem is if I use libraries of 3d party, i do not have the
comfort/certainty of an exception base class that
i can catch, and from which i can get at least a message indicating what is
wrong.
The freedom to do what you want should be used in a responsible, consistent
way.
the problem with 3d part stuff is that their way is not your way. some basic
rules make life more simple.

catch(...) is pretty much useless because no matter if you catch it, you
cannot trust your internal state anymore.
after an unexpected catch(...) i can only tell the user that an internal
error has happened, and that they should
restart the application. the worst is that i can't even diagnose the problem
accuratly.

kind regards,
Bruno.


Carl Daniel [VC++ MVP]

unread,
Sep 17, 2003, 10:54:17 AM9/17/03
to
Bo-Staffan Lankinen wrote:
> That is great news, thanks for the information. Will you be switching
> to table based EH aswell?

I don't believe so. That's a huge change in the compiler, and supporting a
table-based model with /EHs and the current frame based model for /EHa would
be a mess, to say the least.

-cd


Carl Daniel [VC++ MVP]

unread,
Sep 17, 2003, 10:56:17 AM9/17/03
to
Bruno van Dooren wrote:
> myabe a stupid question, but why are not all exceptions derived from
>>> exception?
> I have always found it strange that you can throw any type as an
> exception.

std::exception is a library feature.

throw/catch is a language feature.

The definition of the core language predates the definition of the standard
library by several years. std::exception exists in the library for
precisely the reasons you outline, but the committee's model was to (almost)
never break backwards compatibility, so they chose not to restrict the
language to require that exceptions derive from std::exception, since at the
time the library was designed, that would have broken all existing C++ code
that used exceptions.

-cd


Dan Daly

unread,
Sep 17, 2003, 2:28:41 PM9/17/03
to
Vladimir,

If you check the ARM, you will see that catching of all exceptions in
(...) is defined in the C++ language. MS is just implementing it.

If you do not want to catch SEH exceptions, then you can either:
1) not implement (...)
2) Use set_se_translator and throw an exception type that denotes SEH
exception. Then in your catch(SEHException & e) and rethrow.
Eventually this will lead to a crash, which is what you said you are
after.

Regarding /EHa, yes, if you are using exception handling, then you
should always have this enabled, otherwise you run the risk if missing
some exceptions.

Regarding calling set_se_translator for each thread, just put it into
a DLL and make sure the translator is called for DLL_PROCESS_ATTACH,
and DLL_THREAD_ATTACH.

IMHO, I think that making a program crash so it is easier for a
developer to fix, is missing the forest for the trees! A loss of user
confidence can do wonders for your competitor's sales...

Cheers,
dan

Vladimir Petter

unread,
Sep 17, 2003, 3:58:57 PM9/17/03
to
Dan,

"Dan Daly" <danc...@yahoo.com> wrote in message
news:35eb44f.03091...@posting.google.com...


> Vladimir,
>
> If you check the ARM, you will see that catching of all exceptions in
> (...) is defined in the C++ language. MS is just implementing it.

Chapter 15 of the C++ standart (ISO/IEC 14882:1998(E)) says:

[...]
Exception handling provides a way of transferring control and information
from a point in the execution of
a program to an exception handler associated with a point previously passed
by the execution. A handler
will be invoked only by a throwexpression invoked in code executed in the
handler's try block or in functions
called from the handler's try block .
[...]
throwexpression:`

throw assignmentexpressionopt

[...]

So as you can see Microsoft's implementation contradicts with standard
because handler catches something what
was not thrown using "throwexpression".

Correct me if I am misunderstanding this.

>
> If you do not want to catch SEH exceptions, then you can either:
> 1) not implement (...)
> 2) Use set_se_translator and throw an exception type that denotes SEH
> exception. Then in your catch(SEHException & e) and rethrow.
> Eventually this will lead to a crash, which is what you said you are
> after.
>
> Regarding /EHa, yes, if you are using exception handling, then you
> should always have this enabled, otherwise you run the risk if missing
> some exceptions.
>
> Regarding calling set_se_translator for each thread, just put it into
> a DLL and make sure the translator is called for DLL_PROCESS_ATTACH,
> and DLL_THREAD_ATTACH.

All this is nice, but my point it forces me to do all this complex stuff if
I want to use
catch(...). Without doing this catch(...) feature is compromised. Even if I
do what
you are saying it requires great discipline and a lot of debugging to get it
right.

>
> IMHO, I think that making a program crash so it is easier for a
> developer to fix, is missing the forest for the trees! A loss of user
> confidence can do wonders for your competitor's sales...

Right intentions, but wrong tools :-). I do not think catch(...) is the
right way to achieve process stability. Instead:
- write reliable code
- debug your software
- use __try, __except directly (if you know what you are doing).

Vladimir.

>
> Cheers,
> dan


Bo-Staffan Lankinen

unread,
Sep 17, 2003, 5:37:42 PM9/17/03
to
> I don't believe so. That's a huge change in the compiler, and supporting
a
> table-based model with /EHs and the current frame based model for /EHa
would
> be a mess, to say the least.

I don't think it has to be a mess. AFAIK, the way Metrowerks uses, with CW,
works fine as long as one is aware of the implications of mixing modules
with different EH approaches, which generally shouldn't happen.

Bo-Staffan


Ronald Laeremans [MSFT]

unread,
Sep 17, 2003, 6:29:03 PM9/17/03
to
No we are not. There is too much code out there (e.g. in assembler or other
languages) that people link in that would break when we switch to a table
driven model for X86.

Note that for 64-bit platforms we use a table driven implementation.

Ronald

"Bo-Staffan Lankinen" <ihat...@hotmail.com> wrote in message
news:ObFYDERf...@TK2MSFTNGP09.phx.gbl...

Ronald Laeremans [MSFT]

unread,
Sep 17, 2003, 6:31:59 PM9/17/03
to
As Vladimir states we are definitely not required to have catch(...) catch
non C++ exceptions and a very reasonable interpretation would be that the
standard prevents us from doing so. Another reasonable interpretation would
be that it falls outside of the scope of the standard.

Ronald


Vladimir Petter

unread,
Sep 17, 2003, 7:21:46 PM9/17/03
to
Ronald,

I am just curies. Does the statement
[...]
"A handler will be invoked ONLY BY A THROWEXPRESSION invoked in code


executed in the
handler's try block or in functions called from the handler's try block "

[...]
lives any space for interpretation?
It does not sound like that to me. Standard seams to be restrictive on that.
Am I correct?
So the only thing you could do is to ignore standard.

Vladimir.

"Ronald Laeremans [MSFT]" <ron...@online.microsoft.com> wrote in message

news:esQHDuWf...@tk2msftngp13.phx.gbl...

Carl Daniel [VC++ MVP]

unread,
Sep 17, 2003, 7:41:24 PM9/17/03
to
Vladimir Petter wrote:
> Ronald,
>
> I am just curies. Does the statement
> [...]
> "A handler will be invoked ONLY BY A THROWEXPRESSION invoked in code
> executed in the
> handler's try block or in functions called from the handler's try
> block " [...]
> lives any space for interpretation?
> It does not sound like that to me. Standard seams to be restrictive
> on that. Am I correct?
> So the only thing you could do is to ignore standard.

The issue is this: things that cause SE's to be raised are, in general,
"undefined behavior" according to the standard. As such, whatever happens
when such events occur is outside the scope of the standard.

-cd


Vladimir Petter

unread,
Sep 17, 2003, 7:44:15 PM9/17/03
to

"Carl Daniel [VC++ MVP]" <cpda...@nospam.mvps.org> wrote in message
news:uCad3UXf...@TK2MSFTNGP09.phx.gbl...

But standart explicitly states that they should not be cauched by
C++ exception handlers (see above in uppercase). Am I wrong?

Vladimir

Carl Daniel [VC++ MVP]

unread,
Sep 17, 2003, 8:20:12 PM9/17/03
to
Vladimir Petter wrote:
> "Carl Daniel [VC++ MVP]" <cpda...@nospam.mvps.org> wrote in message
>> The issue is this: things that cause SE's to be raised are, in
>> general, "undefined behavior" according to the standard. As such,
>> whatever happens when such events occur is outside the scope of the
>> standard.
>
> But standart explicitly states that they should not be cauched by
> C++ exception handlers (see above in uppercase). Am I wrong?

I feel, as Ronald said, it's a matter of opinion. In practical terms, what
does it matter? VC has behaved as it does now since before there was a C++
standard, and the next release will in effect let you have either behavior,
according to your needs.

But, see ISO/IES 14882:1998E section 1.9, paragraph 4:

"Note: this International Standard imposes no requirements on the behavior
of programs that contain undefined behavior."

-cd


Dan Daly

unread,
Sep 17, 2003, 8:30:48 PM9/17/03
to
Vladimir,

>So as you can see Microsoft's implementation contradicts with standard
> because handler catches something what
> was not thrown using "throwexpression

So you are assuming that any compiler generated code is incapable of
throwing an exception? If so, why? How is throwing an exception on
something like a null pointer dereference, not following the standard? You
would prefer to define this as invoking "undefined behavior," but to what
end? Exception handling was created to allow for a consistent method of
error handling. The MS implementation facilitates that. In doing so, it
makes programming easier. My only gripe is that the exception has to go
through a "translation" function to become a C++ exception.

>All this is nice, but my point it forces me to do all this complex stuff if
>I want to use
>catch(...). Without doing this catch(...) feature is compromised. Even if I
>do what
>you are saying it requires great discipline and a lot of debugging to get
it
>right.

It's really not that complex if done correctly. Most companies have
"common" libraries that are used in their projects. If you embed your
translation function into one of these, then most of the dirty work is done.
And, you then have the benefit of using one catch clause to handle both C++
and SEH exceptions. Plus, you will know when you get an access violation
versus a widget out of range error. From my experience, most access
violations are not fatal, so having them show up in the eventlog allows you
to fix them before QA even knows there is an issue. And at a customer site,
an error in the eventlog beats the hell out of a crash.


>Right intentions, but wrong tools :-). I do not think catch(...) is the
>right way to achieve process stability. Instead:
> - write reliable code
> - debug your software
> - use __try, __except directly (if you know what you are doing).

Vlad, I hate to break it to you, but code doesn't always work the way we
want it to. That is the whole reason for "exception handling." If you want
to muck you code up with three different types of error handling, that is
your business. But for me, I want one mechanism that works reliablely in
all situations.

Cheers,
dan


Dan Daly

unread,
Sep 17, 2003, 8:54:54 PM9/17/03
to
Ronald,

I bet the group that implemented this had some pretty gnarly discussions...
But all in all, I think they did the right thing. If the intent of
exception handling is to provide a uniform method for handling errors, then
the current implementation meets that criteria.

The alternative would force developers to either use both C++ and SEH
exception handling, or hassle with the translation function. The first is
not uniform. The second is, but probably requires more work than is always
warranted.

dan


Vladimir Petter

unread,
Sep 17, 2003, 8:59:21 PM9/17/03
to

"Carl Daniel [VC++ MVP]" <cpda...@nospam.mvps.org> wrote in message
news:%23sSDjqX...@TK2MSFTNGP11.phx.gbl...

Carl,

You are categorizing program generated by VC++ as
"program that contain undefined behavior" so chapter
15 cannot be applied to it?
:-))

Well then I would agree with you. You can do everything you want.
You can define you own behavior, but do not refer to this behavior as
"interpretation of standard". It is defining an another standard.

In the case of catch(...) you do not have undefined behavior as far as you
follow
standard. Standard clearly defines what implementers of compiler
should/should not
do in this respect. Undefined behavior rather comes as a penalty for
catching
SEH exceptions (violating section 15). Now you are getting in the boundary
of
section 1.9, paragraph 4.

So I still stand that this is not an interpretation of standard. This is a
violation
of standard and as result you have - "program that contain undefined
behavior".

It probably does not have to much sense to continue discussion because as
you pointed I've got what I need (will got with the next release :-) ).

And thanks to Microsoft C++ compiler team that have done a great job in 7.1.

Cheers,
Vladimir.


Vladimir Petter

unread,
Sep 17, 2003, 9:22:42 PM9/17/03
to
"Dan Daly" <dan_...@ortegainfo.com> wrote in message
news:%23JUQXxX...@TK2MSFTNGP12.phx.gbl...

> Vladimir,
>
> >So as you can see Microsoft's implementation contradicts with standard
> > because handler catches something what
> > was not thrown using "throwexpression
>
> So you are assuming that any compiler generated code is incapable of
> throwing an exception? If so, why?

Compiler definetly can do everithing thay want the question is:
- Are they compatible with standard?
and
- Do they break a standard feature?

In respect to catch(...) I think the answer for the first is NO and for the
second is YES.

> How is throwing an exception on
> something like a null pointer dereference, not following the standard?

Dan , please read the quote from the standard I posted. I thing the answer
is in there.

>You
> would prefer to define this as invoking "undefined behavior," but to what
> end?

It is not my definition it is standard definition.

> Exception handling was created to allow for a consistent method of
> error handling. The MS implementation facilitates that. In doing so, it
> makes programming easier. My only gripe is that the exception has to go
> through a "translation" function to become a C++ exception.

I would disagree. I think that implementation breaks catch(...) and even
fails
to provide a good workaround.

>
> >All this is nice, but my point it forces me to do all this complex stuff
if
> >I want to use
> >catch(...). Without doing this catch(...) feature is compromised. Even if
I
> >do what
> >you are saying it requires great discipline and a lot of debugging to get
> it
> >right.
> It's really not that complex if done correctly. Most companies have
> "common" libraries that are used in their projects. If you embed your
> translation function into one of these, then most of the dirty work is
done.
> And, you then have the benefit of using one catch clause to handle both
C++
> and SEH exceptions. Plus, you will know when you get an access violation
> versus a widget out of range error. From my experience, most access
> violations are not fatal, so having them show up in the eventlog allows
you
> to fix them before QA even knows there is an issue. And at a customer
site,
> an error in the eventlog beats the hell out of a crash.

So what you are saying is there are plenty workaround and people are using
them
all around so how comes you are not satisfied :-) ? Well I am using some of
them.
I am simply trying to make the product I am working on more reliable and
wondering how compiler can help me to persuade my goal.

>
>
> >Right intentions, but wrong tools :-). I do not think catch(...) is the
> >right way to achieve process stability. Instead:
> > - write reliable code
> > - debug your software
> > - use __try, __except directly (if you know what you are doing).
>
> Vlad, I hate to break it to you, but code doesn't always work the way we
> want it to. That is the whole reason for "exception handling." If you
want
> to muck you code up with three different types of error handling, that is
> your business. But for me, I want one mechanism that works reliablely in
> all situations.

As Ronald pointed catch(...) is not "mechanism that is working reliably".
On my opinion, no matter what you are using /EHs or /EHa.

Vladimir.


Vladimir Petter

unread,
Sep 18, 2003, 2:10:15 AM9/18/03
to
Carl,

I've read your posting more accurately. Looks like I missed your
point.
I agree with you that SEH is in bound of section 1.9, paragraph 4.

The only thing that leaves me confused is that you guys keep saying
that catching
SEH in catch(…) does not compromise "catch". That this feature in VC++
7.1 (an below)
still 100% confirm to the standard and all this is just matter of
interpretation
of the standard.

What I am saying is that catching SEH in catch(…) puts it (catch) in
the same
place as SHE (in the section 1.9, paragraph 4), violating section 15
and compromising
this language feature in VC++.

Vladimir.


I've read your posting more acurately

Hendrik Schober

unread,
Sep 18, 2003, 4:25:54 AM9/18/03
to
"Dan Daly" <dan_...@ortegainfo.com> wrote:
> [...]

> But all in all, I think they did the right thing. If the intent of
> exception handling is to provide a uniform method for handling errors, then
> the current implementation meets that criteria.

I don't think so.
I do want to do different things in case of a
'std::exception' or one of my own exceptions
than in case of an AV. So I want different
ways to catch them.
How do I do this?

> [...]
> dan

Hendrik Schober

unread,
Sep 18, 2003, 4:17:10 AM9/18/03
to
"Carl Daniel [VC++ MVP]" <cpda...@nospam.mvps.org> wrote:
> [...] so they chose not to restrict the
> language to require that exceptions derive from std::exception [...]

And I'm glad they did.
In the almost ten years I'm asking about this
nobody was able to tell me why the std lib
exceptions don't inherit virtually from their
base class. I think that's stupid, as it makes
it impossible to catch exceptions that are
derived from multiple std lib exceptions as
'std::exception&'.
This is the reason I don't use the std lib
exception hierarchy at all, but invented my own.

> -cd

Hendrik Schober

unread,
Sep 18, 2003, 4:35:26 AM9/18/03
to
"Dan Daly" <dan_...@ortegainfo.com> wrote:
> [...]
> So you are assuming that any compiler generated code is incapable of
> throwing an exception? If so, why?

Who said this?

> How is throwing an exception on

> something like a null pointer dereference, not following the standard? [...]

It is following the standard, but in a very
unfortuante way. Dereferencing a NULL pointer
by the standard is said to invoke undefined
behaviour. This could make demons chasing you
around your office, format your HD, or throw
an exception.
However, while all three literally follow the
standard, I consider them all as pretty bad.
(Although in decresing order. :o> )

> [...] Exception handling was created to allow for a consistent method of
> error handling.

However, it wasn't made for all kinds of
errors.

> The MS implementation facilitates that. In doing so, it
> makes programming easier. My only gripe is that the exception has to go
> through a "translation" function to become a C++ exception.

While that might be true, it doesn't have to
be translated to fake a C++ exception good
enough to be caught as one using 'catch(...)'.
IMHO that's bad.

> [...]


> Vlad, I hate to break it to you, but code doesn't always work the way we
> want it to. That is the whole reason for "exception handling."

I think exception handling as by the C++ std
was invented for when the code behaves as we
want it to, but the world it interacts with
doesn't. (As when someone stumbles over the
network cable.) I don't think they were meant
to deal with buggy code.

> If you want
> to muck you code up with three different types of error handling, that is
> your business. But for me, I want one mechanism that works reliablely in
> all situations.

Nevertheless, many people prefer to have different
error handling strategies for different errors.

> dan

Bo-Staffan Lankinen

unread,
Sep 18, 2003, 7:20:27 AM9/18/03
to
> No we are not. There is too much code out there (e.g. in assembler or
other
> languages) that people link in that would break when we switch to a table
> driven model for X86.
>
> Note that for 64-bit platforms we use a table driven implementation.

I realize that as long as you are going to support asynchronous EH, you're
going to implement that with the code based approach. My intention was not
to ask if you are going to entirely switch to the table based approach, even
though the poorly formulated question implies that, but if you are going to
support the table aswell as the code based approach.

I agree that there are situations where mixing the two models would break
code unless special care is taken, but as long as one know that the C++
exceptions won't propagate through code compiled with a different EH model,
there should be no problems. IME, from working with CW, that model works
just fine.

Bo-Staffan


Daniel James

unread,
Sep 18, 2003, 7:36:54 AM9/18/03
to
In article news:<35eb44f.03091...@posting.google.com>,
Dan Daly wrote:
> If you check the ARM, you will see that catching of all
> exceptions in (...) is defined in the C++ language. MS is
> just implementing it.

Be sensible. The discussion in the ARM is only about C++ exceptions
and doesn't consider Windows SEH exceptions at all. As others have
pointed out the C++ /standard/ states this explicitly.

Given that one can't, in general, use a C++ "catch( x )" block to
catch SEH exceptions; the fact that one can catch them with
catch(...) is pretty clearly unintentional.

Cheers,
Daniel.

Daniel James

unread,
Sep 18, 2003, 7:36:54 AM9/18/03
to
In article news:<O8xl0#XfDHA...@TK2MSFTNGP09.phx.gbl>, Dan Daly
wrote:

> I bet the group that implemented this had some pretty gnarly
> discussions...
> But all in all, I think they did the right thing. If the
> intent of exception handling is to provide a uniform method
> for handling errors, then the current implementation meets
> that criteria.

..but ... the implementation in VC does *not* provide "a uniform
method for handling errors" because C++ exceptions and SEH
exceptions are not uniform types of errors.

In C++ one can write:

try
{
foo();
}
catch( ... )
{
throw;
}

What do you exepct that "throw" do with an SEH exception?

> The alternative would force developers to either use both C++

> and SEH exception handling, ...

That's really the only thing you *can* do as C++ and SEH exceptions
are different in nature and can't sensibly be handled uniformly.

It would be nice to have one consistent handling mechanism that
worked for both C++ and SEH exceptions, but as Windows doesn't make
these different types of exceptions look or work the same way we
have to have to treat them differently (if necessary by translating
one into the other, on occasion).

Cheers,
Daniel.


Craig Powers

unread,
Sep 18, 2003, 9:20:58 AM9/18/03
to

Perhaps for /EHs, but for /EHa it's clearly and unambiguously
documented, which suggests that it is intended behavior.

--
Craig Powers
MVP - Visual C++

Craig Powers

unread,
Sep 18, 2003, 9:22:56 AM9/18/03
to
Vladimir Petter wrote:
>
> "Dan Daly" <dan_...@ortegainfo.com> wrote in message
> news:%23JUQXxX...@TK2MSFTNGP12.phx.gbl...
> > Vladimir,
> >
> > >So as you can see Microsoft's implementation contradicts with standard
> > > because handler catches something what
> > > was not thrown using "throwexpression
> >
> > So you are assuming that any compiler generated code is incapable of
> > throwing an exception? If so, why?
>
> Compiler definetly can do everithing thay want the question is:
> - Are they compatible with standard?
> and
> - Do they break a standard feature?
>
> In respect to catch(...) I think the answer for the first is NO and for the
> second is YES.

If you think catch(...) catching non-C++ exceptions is not compatible
with the standard, can you give an example that does NOT involve
undefined behavior?

Craig Powers

unread,
Sep 18, 2003, 9:27:09 AM9/18/03
to
Vladimir Petter wrote:
>
> "Carl Daniel [VC++ MVP]" <cpda...@nospam.mvps.org> wrote in message
> news:%23sSDjqX...@TK2MSFTNGP11.phx.gbl...

> >
> > But, see ISO/IES 14882:1998E section 1.9, paragraph 4:
> >
> > "Note: this International Standard imposes no requirements on the behavior
> > of programs that contain undefined behavior."
>
> You are categorizing program generated by VC++ as
> "program that contain undefined behavior" so chapter
> 15 cannot be applied to it?
> :-))

No, he's categorizing the circumstances that lead to a SE getting
caught by catch(...) as undefined behavior. Do you have an example
of standard-conforming code (no undefined behavior) that would
produce a structured exception that (contrary to the standard)
would get caught by catch(...)?

Carl Daniel [VC++ MVP]

unread,
Sep 18, 2003, 10:26:40 AM9/18/03
to
Craig Powers wrote:
> Vladimir Petter wrote:

>> In respect to catch(...) I think the answer for the first is NO and
>> for the second is YES.
>
> If you think catch(...) catching non-C++ exceptions is not compatible
> with the standard, can you give an example that does NOT involve
> undefined behavior?

#include <windows.h>
void foo()
{
try
{
RaiseException(STATUS_TIMEOUT, EXCEPTION_NONCONTINUABLE, 0, 0);
}
catch (...)
{
}
}

Of course, one could argue that the internals of RaiseException itself
invoke undefined behavior, which they no doubt do according to a strict
interpretation of the appropriate standards.

-cd


Carl Daniel [VC++ MVP]

unread,
Sep 18, 2003, 10:26:45 AM9/18/03
to
Vladimir Petter wrote:
> Carl,
>
> I've read your posting more accurately. Looks like I missed your
> point.
> I agree with you that SEH is in bound of section 1.9, paragraph 4.
>
> The only thing that leaves me confused is that you guys keep saying
> that catching
> SEH in catch(.) does not compromise "catch". That this feature in VC++

> 7.1 (an below)
> still 100% confirm to the standard and all this is just matter of
> interpretation
> of the standard.
>
> What I am saying is that catching SEH in catch(.) puts it (catch) in

> the same
> place as SHE (in the section 1.9, paragraph 4), violating section 15
> and compromising
> this language feature in VC++.

I think we're all agreed that having catch(...) catch SE's compromises the
utility of catch(...), we're simply arguing that it's compromised in a way
that the Standard allows, since 1.9 basically says that nothing else in the
standard applies once a program invokes undefined behavior. In other words,
once 1.9/4 has been invoked, section 15 of the standard becomes null and
void. Or another view: the undefined behavior that occurs when (for
example), an access violation occurs could be "throw x;", where is is an
object of unspecified type.

That's little solace to the programmer who inadvertantly catches an access
violation with a catch(...), however. For a vast range of programs, simply
having the program terminate when an SE is raised would be better behavior
than having catch(...).

Personally, I've found the ability to catch SEs very useful, but, as you
outlined in the post that started this thread, you must be careful - use
/EHa, use set_se_translator in every thread, etc etc. When used properly,
all of those mechanisms allow one to build more robust programs - programs
that either fail more gracefully, or, under the right conditions, can carry
on in the face of SEs with an acceptable loss of work. (For example, in a
server application that processes requests - it may be possible to abandon
the work for a single request in the face of an SE while not affecting
processing for other, simultaneous requests).

-cd


Vladimir Petter

unread,
Sep 18, 2003, 12:20:10 PM9/18/03
to
I think we agreed here.

Thanks,
Vladimir.

"Carl Daniel [VC++ MVP]" <cpda...@nospam.mvps.org> wrote in message

news:e9fPkDff...@tk2msftngp13.phx.gbl...

Vladimir Petter

unread,
Sep 18, 2003, 1:04:17 PM9/18/03
to

"Craig Powers" <eni...@hal-pc.org> wrote in message
news:3F69B13A...@hal-pc.org...
Craig,

I agree with you that /EHa clearly defines that programmer expecting
exceptions at any time (including SEH), but catching everything in the
catch(...)
still is not desirable, (at least for me) because the way C++ and
SEH exceptions should be handled are different (as somebody already
pointed here). I would rather prefer some C++ language extension like
try{
RaiseException or throw
} catch (std::exception &) {
} catch (...) {
} __except (FILTER) {
//handle non C++ exceptions
}
In this way I would be able easily distinguish them and handle properly
and unambiguitly.
You may argue that _set_se_translator let me do exactly that, but
unfortunately
it has 2 side effects:

1. I have to attach it to every thread. What if in the same process I have
modules from different vendors in that case I do not know which handler
is translating. Different vendors may translate SEH to different C++
classes.
So we got undefined behavior again.

2. Even if you lucky and do not have any third party modules in your process
it is still
has some pitfalls You can accidentally catch exception that not supposed to
be cached:
try{
try{
//raise SEH exception
} catch (SEH_exception &) {
throw; //propagate it forward
} catch (...) {
//SEH never comes here
}
} catch (...) {
//UUUPS!!! we got SEH_exception here
}

In other words " } catch (SEH_exception &) {" always should come in from
of
catch(...)


All though I do understand Microsoft why they are not changing this.
It could break a lot of existing programs.

Cheers.
Vladimir


Carl Daniel [VC++ MVP]

unread,
Sep 18, 2003, 1:13:36 PM9/18/03
to
Craig Powers wrote:

> Daniel James wrote:
>> Given that one can't, in general, use a C++ "catch( x )" block to
>> catch SEH exceptions; the fact that one can catch them with
>> catch(...) is pretty clearly unintentional.
>
> Perhaps for /EHs, but for /EHa it's clearly and unambiguously
> documented, which suggests that it is intended behavior.

If we set the way-back machine (and if memory serves), VC has supported
catching SE's with the C++ catch(...) statement since "VC++ 1.0 32 bit
edition". The "synchronous" exception handling, /EHs, was a relatively
recent introduction that appeared in VC4 or 5. Clearly the behavior is
intentional. What was missing was a detailed discussion about the effects
of SEs on C++ code when compiled with /EHs.

-cd


Dan Daly

unread,
Sep 18, 2003, 2:17:02 PM9/18/03
to
Daniel,

> ..but ... the implementation in VC does *not* provide "a uniform
> method for handling errors" because C++ exceptions and SEH
> exceptions are not uniform types of errors.

Says who? If I check all pointers for validity before accessing them, and
throw a MyBadPointer when I encounter and invalid pointer, how is this
different than an SEH being raised for the same bad pointer? The fact is,
they are the same damn thing! So why not handle them the same way?

dan


Dan Daly

unread,
Sep 18, 2003, 2:52:45 PM9/18/03
to
Schobi,

> It is following the standard, but in a very
> unfortuante way. Dereferencing a NULL pointer
> by the standard is said to invoke undefined
> behaviour. This could make demons chasing you
> around your office, format your HD, or throw
> an exception.
> However, while all three literally follow the
> standard, I consider them all as pretty bad.
> (Although in decresing order. :o> )

So if I check my pointers before accessing them, and throw a MyBadPointer
exception when one is bad, this is different than an SEH generated by the
same action?


> > [...] Exception handling was created to allow for a consistent method of
> > error handling.
>
> However, it wasn't made for all kinds of
> errors.

Really? So, which ones did it mean to exclude and why?


> > The MS implementation facilitates that. In doing so, it
> > makes programming easier. My only gripe is that the exception has to go
> > through a "translation" function to become a C++ exception.
>
> While that might be true, it doesn't have to
> be translated to fake a C++ exception good
> enough to be caught as one using 'catch(...)'.
> IMHO that's bad.

I 'm not sure I understand. If you are saying catching them in (...) is
generally bad, I would agree.

> I think exception handling as by the C++ std
> was invented for when the code behaves as we
> want it to, but the world it interacts with
> doesn't. (As when someone stumbles over the
> network cable.) I don't think they were meant
> to deal with buggy code.

No, it was designed to handle "exceptional conditions." That is roughly
defined as things that go wrong for whatever reason. Unfortunately, bugs
are part of coding. If a bug introduces an exceptional condition, then it
is best handled by exception handling, IMHO.

> Nevertheless, many people prefer to have different
> error handling strategies for different errors.

There is a difference between errors and exceptions, I hope we aren't mixing
them up here. Exceptions should not occur, but when they do, I want one way
to handle them so I can identify and fix them quickly. Errors should and
will occur, like bad password, etc., these kind of conditions are not
exceptional, but likely to occur and need to be handled on a case by case
basis.

dna


Dan Daly

unread,
Sep 18, 2003, 3:03:25 PM9/18/03
to

"Daniel James" <waste...@nospam.aaisp.org> wrote in message
news:VA.0000038...@nospam.aaisp.org...

It is you who is not being sensible. Think about it. Exception handling is
designed to handle "exceptional conditions." If accessing an invalid
pointer is not an exceptional condition, then what is it? Undefined
behaviour? Rubbish! Where does that leave us? Works as designed.

Once again, what is the difference between checking all pointers and
throwing a MyBadPointer exception, and the compiler raising and SEH on the
very same pointer?

dan


Vladimir Petter

unread,
Sep 18, 2003, 3:08:28 PM9/18/03
to

"Dan Daly" <dan_...@ortegainfo.com> wrote in message
news:uRKmKFhf...@TK2MSFTNGP12.phx.gbl...

Dan,

In this case you are using two different mechanisms. If you are throwing
MyBadPointer
you are using C++ if you are explicitly expecting AV during dereferencing
then you are
using SEH. In VC++ implementation C++ exceptions are based on SEH exceptions
so we all got used to that "they are the same damn thing". If you look
broader then in mater
(other platforms or other compilers for MS) of fact this two mechanisms are
not the same.
They just look alike.
And the problem is that in VC++ catch(...) stays on the intersection those
two without
providing a sufficient (this is just my point of view) way to resolve
ambiguity caused by
that.

You see the problem is that current catch(...) putting you in a probability
game (somebody
stated something like "well catch SEH exception in catch(...) and continue
works in 95% for
me"). But would not this be better first extract from here all the cases we
are sure about for
100% (C++ exceptions and SEH exceptions that are designed) and then apply
probability
for others (SEH exceptions if they are not designed). Would not this give
you more control
with less efforts?

Do we have this option?
We do not have this option for /EHs - because destructors may not be called
so in general
it is not recommended handle SEH exceptions in this case
We do have a cumbersome, in general unreliable (e.g. you have modules from
different vendors
and both are trying to install there exception translators) solution for
/EHa

I would certainly prefer some kind language extension like:


try{
RaiseException or throw
} catch (std::exception &) {
} catch (...) {
} __except (FILTER) {
//handle non C++ exceptions
}

Vladimir.


Craig Powers

unread,
Sep 18, 2003, 7:42:21 PM9/18/03
to
Dan Daly wrote:
>
> > It is following the standard, but in a very
> > unfortuante way. Dereferencing a NULL pointer
> > by the standard is said to invoke undefined
> > behaviour. This could make demons chasing you
> > around your office, format your HD, or throw
> > an exception.
> > However, while all three literally follow the
> > standard, I consider them all as pretty bad.
> > (Although in decresing order. :o> )
>
> So if I check my pointers before accessing them, and throw a MyBadPointer
> exception when one is bad, this is different than an SEH generated by the
> same action?

Yes. One is explicitly thrown by your own code and has behavior that
is guaranteed by the C++ standard. The other is produced by the
operating system; VC happens to handle it correctly (with the right
build settings, and correctly in the sense that it will do the stack
unwinding right), but is under no obligations to do anything of the
sort by the C++ standard.

Indeed, I doubt *nix-based compilers will offer an opportunity to
handle something like a null pointer dereference with a C++
exception handler.

Ronald Laeremans [MSFT]

unread,
Sep 18, 2003, 8:05:39 PM9/18/03
to
I am afraid that the fastest way to get there will be 32-bit platforms
becoming extinct. That might not be so far away.

Ronald

"Bo-Staffan Lankinen" <ihat...@hotmail.com> wrote in message
news:ui%23L$adfDH...@TK2MSFTNGP09.phx.gbl...

Bruno van Dooren

unread,
Sep 19, 2003, 2:06:51 AM9/19/03
to

> It is you who is not being sensible. Think about it. Exception handling
is
> designed to handle "exceptional conditions." If accessing an invalid
> pointer is not an exceptional condition, then what is it? Undefined
> behaviour? Rubbish! Where does that leave us? Works as designed.

i agree that dereferencing a null pointer should raise an exception.
it would make life easier.
the same for deleting an element twice.

i don't mind the fact that an app crashes in such circumstances,
but it would be nice to at least diagnose the problem.

kind regards,
Bruno.


Daniel James

unread,
Sep 19, 2003, 5:35:56 AM9/19/03
to
In article news:<uRKmKFhf...@TK2MSFTNGP12.phx.gbl>, Dan Daly
wrote:

> > ..but ... the implementation in VC does *not* provide "a
> > uniform method for handling errors" because C++ exceptions
> > and SEH exceptions are not uniform types of errors.
>
> Says who?

Says Microsoft, for one. Read the docs on Windows SEH.

The mechanism by which SEH exceptions are "thrown" (or "raised" if
you prefer) is not the same as the mechanism by which C++
exceptions are thrown. It might be nice if is was, but it isn't.

> If I check all pointers for validity before accessing them,
> and throw a MyBadPointer when I encounter and invalid pointer,
> how is this different than an SEH being raised for the same
> bad pointer?

You're talking about two different types of exception that have
the same meaning but are implemented differently 'under the hood'.

The exception /conditions/ are the same (bad pointer), but the
actual exceptions are different.

Cheers,
Daniel.

Hendrik Schober

unread,
Sep 19, 2003, 5:52:07 AM9/19/03
to
"Dan Daly" <dan_...@ortegainfo.com> wrote:
> [...]
> So if I check my pointers before accessing them, and throw a MyBadPointer
> exception when one is bad, this is different than an SEH generated by the
> same action?

Indeed. The difference is, the SEH is generated
by the run-time system in response to what's
most likely an error of the programmer (i.e., a
bug). While it could be intentional, it might as
well not be, which is why I think mixing the two
hides errors and is bad style.
On the contrary, if I have this:

int f(int* ptr)
{
if( isBadPtr(ptr) ) {
return -1;
}
return calculate(*ptr);
}

then passing a bad 'ptr' to 'f()' is expected and
will lead to a predictable error (and therefore
should be well documented in 'f()'s documentation).

> > > [...] Exception handling was created to allow for a consistent method of
> > > error handling.
> >
> > However, it wasn't made for all kinds of
> > errors.
> Really? So, which ones did it mean to exclude and why?

It was meant to handle expected errors. It was
not meant to handle bugs. As to the why... The
guys in the std committee decided so, based on
their experience. Whether you and me think that
is good, doesn't matter. It's what C++ has been
standardized to.

> > > The MS implementation facilitates that. In doing so, it
> > > makes programming easier. My only gripe is that the exception has to go
> > > through a "translation" function to become a C++ exception.
> >
> > While that might be true, it doesn't have to
> > be translated to fake a C++ exception good
> > enough to be caught as one using 'catch(...)'.
> > IMHO that's bad.
> I 'm not sure I understand. If you are saying catching them in (...) is
> generally bad, I would agree.

I struggled to say (I'm a German, sorry) that,
in the case of 'catch(...)', SE's fake as C++
exceptions good enough to fool you. I think
that's bad.

> > I think exception handling as by the C++ std
> > was invented for when the code behaves as we
> > want it to, but the world it interacts with

> > doesn't. [...]
> No, it was designed to handle "exceptional conditions." [...]

Proof this.

> > Nevertheless, many people prefer to have different
> > error handling strategies for different errors.
> There is a difference between errors and exceptions, I hope we aren't mixing
> them up here. Exceptions should not occur, but when they do, I want one way
> to handle them so I can identify and fix them quickly. Errors should and
> will occur, like bad password, etc., these kind of conditions are not
> exceptional, but likely to occur and need to be handled on a case by case
> basis.

That's your definition for "exception" and
"error". While I don't say that's bad, I didn't
use this one.
What I use is this:
1. Things that are very probable to fail, like
trying to open a file with a file name that
was provided by the user.
I'd use return values to indicate error here.
2. Things that are rather unlikely to fail, like
an app parsing and syntax-checking a file that
was written by itself.
I would use C++ exceptions here and try to tell
the user he/she either shouldn't mess with the
app's internal files or should run a checkdisk.
3. Things which should not fail, like that lttle
function I wrote the other day, which implements
a very simple algorithm where I nevertheless
managed to screw up, so that it sometimes
causes to dereference a NULL pointer.
This should put a scary message on the scrren
for the user and make me fire up the debugger
and fix that stupid bug.
These all are errors. (Either the user's, or the
disk manufacturer's, or mine.) And I want them to
be treated differently.

> dna

Hendrik Schober

unread,
Sep 19, 2003, 5:56:47 AM9/19/03
to
"Dan Daly" <dan_...@ortegainfo.com> wrote:
> [...] Exception handling is

> designed to handle "exceptional conditions." If accessing an invalid
> pointer is not an exceptional condition, then what is it?

It's a bug. It shouldn't happen. The
programmer(s) failed.

> Undefined
> behaviour? Rubbish!

Well, it does lead to very different things
on different machines, OS's, or when using
different compilers. Yet all these behaviours
are conformant with the C++ std.
You may not like it, but that's what's called
"undefined behaviour".

> Where does that leave us? Works as designed.

You design to dereference NULL pointers?
Pray you never have to port your code to
another platform.

> Once again, what is the difference between checking all pointers and
> throwing a MyBadPointer exception, and the compiler raising and SEH on the
> very same pointer?

It's the same difference as between checking
whether a file open operation succeeded or
just accessing an invalid 'FILE*': The first
one is a check for a somewhat expected error,
the second one is a bug.

> dan

Bo-Staffan Lankinen

unread,
Sep 19, 2003, 5:59:47 AM9/19/03
to
> It is you who is not being sensible. Think about it. Exception handling
is
> designed to handle "exceptional conditions." If accessing an invalid
> pointer is not an exceptional condition, then what is it? Undefined
> behaviour? Rubbish! Where does that leave us? Works as designed.
>
> Once again, what is the difference between checking all pointers and
> throwing a MyBadPointer exception, and the compiler raising and SEH on the
> very same pointer?

When writing exception safe code, it's essential to be able to rely on the
semantics of the C++ standard. SEH violates those semantics and can leave
the program in an undefined state, which for instance can result in loss of
data or worse. An access violation, illegal instruction or some other
CPU-exception is almost always an indication of a bug in the program and
should generally be dealt with differently (ie debugging) than an C++
exception, which has a defined behavior. Having the CPU-exceptions patch in
to the C++ EH is unfortunate. Besides of having the potential of leaving the
program in an undefined state, it's prone to letting bugs slip through into
the released application.

Bo-Staffan


Bo-Staffan Lankinen

unread,
Sep 19, 2003, 6:05:01 AM9/19/03
to
> i agree that dereferencing a null pointer should raise an exception.
> it would make life easier.
> the same for deleting an element twice.
>
> i don't mind the fact that an app crashes in such circumstances,
> but it would be nice to at least diagnose the problem.

I don't think anyone is arguing against the usefullness of CPU-exceptions.
The problem is that SEH is patched into the C++ EH which violates the C++
standard and the implications that can have on an application.

Bo-Staffan


Carl Daniel [VC++ MVP]

unread,
Sep 19, 2003, 10:15:51 AM9/19/03
to
Bo-Staffan Lankinen wrote:
> Having the CPU-exceptions patch in to the C++ EH is
> unfortunate.

A small clarification: VC++ does not "patch CPU exceptions into the C++
EH", rather, it makes C++ exceptions look like CPU exceptions. In most
regards, this is a "Good Thing", since it does provide a single way of
handling exceptions: the Windows-specific Structured Exception Handling
way. The unfortunate thing is that they decided to make catch(...) "see"
other exceptions besides C++ exceptions.

-cd


Bo-Staffan Lankinen

unread,
Sep 19, 2003, 12:37:20 PM9/19/03
to
> A small clarification: VC++ does not "patch CPU exceptions into the C++
> EH", rather, it makes C++ exceptions look like CPU exceptions. In most
> regards, this is a "Good Thing", since it does provide a single way of
> handling exceptions: the Windows-specific Structured Exception Handling
> way.

I don't see the need for providing a single way of handling two different
exception types with different restrictions. Generally, a C++-exception
should be caught by a C++ EH and an SEH-exception should be caught by a
SEH-handler.

> The unfortunate thing is that they decided to make catch(...) "see"
> other exceptions besides C++ exceptions.

Agreed, that was the point I was trying to make.

Bo-Staffan


Craig Powers

unread,
Sep 19, 2003, 6:58:15 PM9/19/03
to

In what sense does it violate the C++ standard?

Brandon Bray [MSFT]

unread,
Sep 19, 2003, 9:43:40 PM9/19/03
to
Bo-Staffan Lankinen wrote:
> When writing exception safe code, it's essential to be able to rely on the
> semantics of the C++ standard. SEH violates those semantics and can leave
> the program in an undefined state, which for instance can result in loss
> of data or worse. An access violation, illegal instruction or some other
> CPU-exception is almost always an indication of a bug in the program and
> should generally be dealt with differently (ie debugging) than an C++
> exception, which has a defined behavior.

Hi Bo-Staffan,
What you've described above is exactly what /EHs provides. Standard C++
provides no language facilities for dealing with access violations. If you
compile entirely with /EHs, the Standard C++ language constructs will not
deal with these machine exceptions.

By using /EHa, the program is declaring its intent to deal with undefined
behavior in the standard. While there are many design decisions that could
be changed on the second time around, the behavior that is available for
/EHa is consistent, documented, and manageable.

> Having the CPU-exceptions patch in to the C++ EH is unfortunate. Besides
> of having the potential of leaving the program in an undefined state, it's
> prone to letting bugs slip through into the released application.

Again, the underlying architecture only shows through for /EHa (of course,
I'm talking about the next version of Visual C++). Unifying the underlying
architecture has a number of advantages, especially for system level
programming. If anything, the right thing to do is provide more control to
the programmer to deal with different kinds of exceptions. We certainly have
thought about this, and our top concern is not breaking existing code. Some
things are being fixed in Whidbey (like not catching SEH in catch(...) under
EHs), other things will be fixed later when we can evaluate the right
solution.

Cheerio!

--
Brandon Bray Visual C++ Compiler
This posting is provided AS IS with no warranties, and confers no rights.


Bo-Staffan Lankinen

unread,
Sep 20, 2003, 6:15:36 AM9/20/03
to
> In what sense does it violate the C++ standard?

I guess it's argueble whether defining UB, in a way that changes the defined
behavior of some other part of the standard, is conformant or not. Maybe I
should have written that it violates the semantics of the defined behavior
in the standard. However, conformant or not, IMO it's an unwise decision
because you might be relying on exception safe code that is written with the
standard behavior in mind that silently leaves the program in an corrupted
state. That kind of errors can be very hard to track down because usually
they manifests themselfs at a much later stage. Neglecting exception safety
is IMO one of the most common reason for hard-to-find bugs.

Bo-Staffan


Bo-Staffan Lankinen

unread,
Sep 20, 2003, 6:16:42 AM9/20/03
to
> What you've described above is exactly what /EHs provides. Standard C++
> provides no language facilities for dealing with access violations. If you
> compile entirely with /EHs, the Standard C++ language constructs will not
> deal with these machine exceptions.
>
> By using /EHa, the program is declaring its intent to deal with undefined
> behavior in the standard. While there are many design decisions that could
> be changed on the second time around, the behavior that is available for
> /EHa is consistent, documented, and manageable.

With the current definition of UB I think it's unclear whether an
implementor should be allowed to define UB in a way that contradicts the
defined behavior expressed in the standard and still be conformant. I'm
confident that wasn't the intention of the committee. IMO, it defeats the
entire purpose of a standard.

I can understand your decisions for having and maintaining the asynchronous
model. Both for legacy reasons and the fact that there are situations where
that model can be preferable. However, including the asynchronous model is
only justified as long as it's possible to have the standard behavior and
IMO that should be the default model.

> Again, the underlying architecture only shows through for /EHa (of course,
> I'm talking about the next version of Visual C++). Unifying the underlying
> architecture has a number of advantages, especially for system level
> programming. If anything, the right thing to do is provide more control to
> the programmer to deal with different kinds of exceptions. We certainly
have
> thought about this, and our top concern is not breaking existing code.
Some
> things are being fixed in Whidbey (like not catching SEH in catch(...)
under
> EHs), other things will be fixed later when we can evaluate the right
> solution.

That's good to hear. I'm looking forward to the next release.

Bo-Staffan


Vladimir Petter

unread,
Sep 22, 2003, 1:18:20 PM9/22/03
to
Hi,
 
Looks like there is a solutions that I've overlooked so far.
 
The solution lets you more reliably split SEH and C++ exceptions
in /EHs and /EHa modes.
 
The idea is to use "throw" in the SE translator rather then "throw SEH_exceptin()"
(as it was in my previous sample).
In this case exception passes through all C++ handlers not couched.
 
This solution is more superior comparing with throwing a class from translator:
 
1. You do not need put "catch( SEH_exceptin& )" (as it was in my
previous sample) before "catch(...)"
2. As result you can not accidentally catch it if you forgot (1)
3. If you have code from multiply vendors trying to install translator
this implementation of translator does not introduce ambiguity.
4. You still can use SEH __try/__except to deal with SEH if
you want to.
 
Vladimir.
 
#include <windows.h>
#include "eh.h"
#include "exception"
#include "iostream"
#include "process.h"
 
typedef void (*se_translaor_t)(unsigned int code, PEXCEPTION_POINTERS ex);
 

struct se_translator {
 static se_translaor_t install(se_translaor_t new_se_translator=se_translator::default_se_translator){
  se_translaor_t previose_se_translator = _set_se_translator(new_se_translator);
  std::cout << "scopped_se_translator was set to " << new_se_translator << std::endl;
  std::cout.flush();
  return previose_se_translator;
 }
 
private:
 static void default_se_translator(unsigned int code, PEXCEPTION_POINTERS ex) {
    std::cout << "se_translator throw SEH_exception, SEH code=" << code << std::endl;
    std::cout.flush();
    throw;
 }
};
 
class bogus_class {
public:
 void assync_exception() {
  try{
   char *bogus_pointer = NULL;
            *bogus_pointer = 'a';
  } catch (std::exception &ex) {
   std::cout << "bogus_class::assync_exception catched " << ex.what() << std::endl;
   std::cout.flush();
  } catch (...) {
   std::cout << "bogus_class::assync_exception catched catch(...)" << std::endl;
   std::cout.flush();
  }
  std::cout << "assync_exception finished" << std::endl;
 }
 void sync_exception() {
  try{
   throw 1;
  } catch (std::exception &ex) {
   std::cout << "bogus_class::sync_exception catched " << ex.what() << std::endl;
   std::cout.flush();
  } catch (...) {
   std::cout << "bogus_class::sync_exception catched catch(...)" << std::endl;
   std::cout.flush();
  }
  std::cout << "sync_exception finished" << std::endl;
 }
};
 
int main(int argc, TCHAR* argv[]){
 se_translator::install();
 try{
  bogus_class c;
  c.sync_exception();
  c.assync_exception();
 } catch (std::exception &ex) {
  std::cout << "main catched " << ex.what() << std::endl;
  std::cout.flush();
 } catch (...) {
  std::cout << "main catched catch(...)" << std::endl;
  std::cout.flush();
 }
 std::cout << "main finished" << std::endl;
    return 0;
}

Dan Daly

unread,
Sep 22, 2003, 1:54:30 PM9/22/03
to
Daniel,

> You're talking about two different types of exception that have
> the same meaning but are implemented differently 'under the hood'.
>
> The exception /conditions/ are the same (bad pointer), but the
> actual exceptions are different.

Semantically they are the same. IMHO, this is all that really matters.

dan


Vladimir Petter

unread,
Sep 22, 2003, 1:58:41 PM9/22/03
to
By the way it would make sense to put this technique in the KB
if there is no other impact of using it.
If somebody from Microsoft or guys working close with them could
do that it would be helpful.
 
Vladimir.
"Vladimir Petter" <vla...@hotmail.com> wrote in message news:eSc0T3S...@TK2MSFTNGP11.phx.gbl...

Dan Daly

unread,
Sep 22, 2003, 2:29:56 PM9/22/03
to
Schobi,

> then passing a bad 'ptr' to 'f()' is expected and
> will lead to a predictable error (and therefore
> should be well documented in 'f()'s documentation).

But in the end, we are still taking about the same behavior, an exception
gets thrown, and it gets caught and the program is better for it. I belive
that is the whole point.

> It was meant to handle expected errors. It was
> not meant to handle bugs. As to the why... The
> guys in the std committee decided so, based on
> their experience. Whether you and me think that
> is good, doesn't matter. It's what C++ has been
> standardized to.

Well with that in mind, what should happen to "bugs?"

> I struggled to say (I'm a German, sorry) that,
> in the case of 'catch(...)', SE's fake as C++
> exceptions good enough to fool you. I think
> that's bad.

Well, your English is a hell of a lot better than my German! Yes, I see
what you mean. I believe that is what Vladimir was troubled with also. But
I am unclear on what you want to happen with these 'fake C++ exceptions.'
Do you also want a language extension?

> > > I think exception handling as by the C++ std
> > > was invented for when the code behaves as we
> > > want it to, but the world it interacts with
> > > doesn't. [...]
> > No, it was designed to handle "exceptional conditions." [...]
>
> Proof this.

Right now the best I can do is point you to _The Design and Evolution of
C++__ by Stroustrup, pg 384,
- exceptions are a "mechanism by which a subsystem can be given a large
measure of fault tolerance..."

This looks like my list too. But regarding 3., what if this code is running
on a customer site? You still want it to GP?


dan


Dan Daly

unread,
Sep 22, 2003, 2:44:36 PM9/22/03
to
Bo-Staffan,

> However, conformant or not, IMO it's an unwise decision
> because you might be relying on exception safe code that is written with
the
> standard behavior in mind that silently leaves the program in an corrupted
> state. That kind of errors can be very hard to track down because usually
> they manifests themselfs at a much later stage. Neglecting exception
safety
> is IMO one of the most common reason for hard-to-find bugs.

Yes, I think we are all in agreement that an unattended access violation can
lead to some very bad, and hard to find bugs. But we have also pointed out
that you can figure out all SEH's and use that information to your
advantage. If when your translation function gets called, you can set the
exception code and message, then in your generic handler you can log it so
you know when and where it happened.

dan


Dan Daly

unread,
Sep 22, 2003, 3:01:24 PM9/22/03
to
Craig,

> Indeed, I doubt *nix-based compilers will offer an opportunity to
> handle something like a null pointer dereference with a C++
> exception handler.

That is a good point. And must lead to some pretty kludgy code...

Does anyone know how null pointer dereference is handled by *nix
programmers? Is there and existing idiom? Or is it just, burn baby, burn!

Cheers,
dan


Craig Powers

unread,
Sep 22, 2003, 3:46:02 PM9/22/03
to
Bo-Staffan Lankinen wrote:
>
> > In what sense does it violate the C++ standard?
>
> I guess it's argueble whether defining UB, in a way that changes the defined
> behavior of some other part of the standard, is conformant or not. Maybe I
> should have written that it violates the semantics of the defined behavior
> in the standard.

The thing is, though, as far as I can see it only ever goes against
the written word of the standard in situations where undefined behavior
has occurred, at which point the implementation has license to do
anything it wants (insert gratuitous comment about formatting your hard
drive, emailing your boss, or nasal demons here).

> However, conformant or not, IMO it's an unwise decision
> because you might be relying on exception safe code that is written with the
> standard behavior in mind that silently leaves the program in an corrupted
> state.

The problem, of course, is that to have gone into the corrupted state,
your program will have already done something undefined. Even then,
although catch(...) is unlikely to do the right thing, there are tools
at your disposal to avoid the problem, most notably _set_se_translator.

> That kind of errors can be very hard to track down because usually
> they manifests themselfs at a much later stage. Neglecting exception safety
> is IMO one of the most common reason for hard-to-find bugs.

If you run into problems with catch(...), your problems are more
fundamental than neglect of exception safety.

Dan Daly

unread,
Sep 22, 2003, 4:43:11 PM9/22/03
to
Vladimir,

> And the problem is that in VC++ catch(...) stays on the intersection those
> two without
> providing a sufficient (this is just my point of view) way to resolve
> ambiguity caused by
> that.

There is no ambugity if you use the tranlation function.


> I would certainly prefer some kind language extension like:
> try{
> RaiseException or throw
> } catch (std::exception &) {
> } catch (...) {
> } __except (FILTER) {
> //handle non C++ exceptions
> }

Ok, so if you wrote it like:
try{... }catch(...)
{...}

Then your exception would be caught in the (...), so what is the difference?
Do you want to change the meaning of (...) also?

Cheers,
dan


Dan Daly

unread,
Sep 22, 2003, 5:34:56 PM9/22/03
to
> If you run into problems with catch(...), your problems are more
> fundamental than neglect of exception safety.

I think Craig summed it up right here.

dan


Dan Daly

unread,
Sep 22, 2003, 5:57:53 PM9/22/03
to
Schobi,

> > [...] Exception handling is
> > designed to handle "exceptional conditions." If accessing an invalid
> > pointer is not an exceptional condition, then what is it?
>
> It's a bug. It shouldn't happen. The
> programmer(s) failed.
>

Yes, but bugs do happen. Do you really want you end uses to experience a
crash every time you create one?

> Well, it does lead to very different things
> on different machines, OS's, or when using
> different compilers. Yet all these behaviours
> are conformant with the C++ std.
> You may not like it, but that's what's called
> "undefined behaviour".
>
> > Where does that leave us? Works as designed.
>
> You design to dereference NULL pointers?
> Pray you never have to port your code to
> another platform.
>

Haven't you heard? There is only one platform! "Porting" is just another
way of saying you can't sell your product.

> > Once again, what is the difference between checking all pointers and
> > throwing a MyBadPointer exception, and the compiler raising and SEH on
the
> > very same pointer?
>
> It's the same difference as between checking
> whether a file open operation succeeded or
> just accessing an invalid 'FILE*': The first
> one is a check for a somewhat expected error,
> the second one is a bug.
>

Yes, I agree. But imagine you make a call to a library or function (written
by someone else of course) right after you open your file successfully. So
as far as you are concerned, you have a valid file handle. But in reality,
that library call just trounced on it, or closed it. So the next time you
access it - boom. Do you want to be setup to handle this bug? Or do you
just want to throw your hands up and say "let the user send us a crash
dump?"

Cheers,
dan


Dan Daly

unread,
Sep 22, 2003, 6:05:33 PM9/22/03
to
>The idea is to use "throw" in the SE translator rather then "throw
SEH_exceptin()"
>(as it was in my previous sample).
>In this case exception passes through all C++ handlers not couched.
>
But Vladimir, I though you had decided that the translator was too much
trouble and "complex stuff "? Are you now endorsing it?

Cheers,
dan


Vladimir Petter

unread,
Sep 22, 2003, 6:17:27 PM9/22/03
to
Dan,

Please, do not cut my word out of context.
This technique and technical we discussed before requires different
efforts, have different implications and produce different results.

See sources closely.

Vladimir.

"Dan Daly" <danc...@yahoo.com> wrote in message
news:%23BfakXV...@TK2MSFTNGP09.phx.gbl...

Vladimir Petter

unread,
Sep 22, 2003, 6:23:00 PM9/22/03
to
Dan,

> Vladimir,
>
> > And the problem is that in VC++ catch(...) stays on the intersection
those
> > two without
> > providing a sufficient (this is just my point of view) way to resolve
> > ambiguity caused by
> > that.
> There is no ambugity if you use the tranlation function.

As I wrote the ambiguity is an issue if you have exception translators
from different vendors. Lets assume you have 2 dlls installing translation
handlers and because they came from different vendors you can not
guaranty that they will throw same C++ class. In this case catch(...) still
could
catch exception (play a little bit with program I've put in my first
posting).
This will defeat my purpose (crash if unexpected SEH exception).
All though see my last postings there is a way to solve this by using
"throw;" instead of "throw SEH_exception();" in the translator.
If all 3'rd party handlers would do the same (which is unlikely counting
that if
3'rd party would be you or Crayg you would throw C++ class :-)) ) then
I am happy otherwise it would not work.

>
>
> > I would certainly prefer some kind language extension like:
> > try{
> > RaiseException or throw
> > } catch (std::exception &) {
> > } catch (...) {
> > } __except (FILTER) {
> > //handle non C++ exceptions
> > }
> Ok, so if you wrote it like:
> try{... }catch(...)
> {...}
>
> Then your exception would be caught in the (...), so what is the
difference?
> Do you want to change the meaning of (...) also?

I've already expressed my point of view on the in other posting.
I am certainly do not like about current "catch(...)" makes a mess
from all unhandled C++ exceptions and all SEH exceptions.

- First It would be much better to live in the catch(...) only C++
exceptions in the catch block this would make it as safe as it
was designed in the C++ standard.
- Second some developers do not like __try/__except in some reasons so
I thought that VC++ could in general extend language letting handle SEH
exceptions
in a special block where you have enough information (I am assuming
GetExceptionInformation is available there) to make decision.

Dan,

I do not want to go again into discussion if letting application crash
(from my point it is equal having developer to fix his bugs) is right or
bad.
It is sounds more and more like wholly war of PASCAL and C.
If you was not convinced so far I hardly believe you will be convinced ever.
If for you 95% stability is enough then fine.
All though probability theory says that it does not mean you would not get
into unfortunate 5% N times in a row and then you will have much more
trouble
then if you let you program crash on first place and study it.

Vladimir.

>
> Cheers,
> dan
>
>


Dan Daly

unread,
Sep 22, 2003, 9:42:40 PM9/22/03
to
Vlad,

> Please, do not cut my word out of context.
> This technique and technical we discussed before requires different
> efforts, have different implications and produce different results.
>
> See sources closely.
>

I don't think they are out of context... I agree with you that installing
the translator has its pitfalls. I've looked at your code, but don't see
how it eliminates all of the issues you brought up earlier. It still looks
like "complex stuff" to me...

dan


Dan Daly

unread,
Sep 22, 2003, 10:24:01 PM9/22/03
to
Vladimir,

> 3'rd party would be you or Crayg you would throw C++ class :-)) ) then
> I am happy otherwise it would not work.

Yes. Craig and I live to mess you, otherwise conscientious, programmers up!

> > Then your exception would be caught in the (...), so what is the
> difference?
> > Do you want to change the meaning of (...) also?
>
> I've already expressed my point of view on the in other posting.
> I am certainly do not like about current "catch(...)" makes a mess
> from all unhandled C++ exceptions and all SEH exceptions.
>
> - First It would be much better to live in the catch(...) only C++
> exceptions in the catch block this would make it as safe as it
> was designed in the C++ standard.
> - Second some developers do not like __try/__except in some reasons so
> I thought that VC++ could in general extend language letting handle SEH
> exceptions
> in a special block where you have enough information (I am assuming
> GetExceptionInformation is available there) to make decision.
>

I wan't trying to restart that debate. I thought you wanted some sort of
special attributes on the SEH exceptions so that they were only caught by
__except.

> I do not want to go again into discussion if letting application crash
> (from my point it is equal having developer to fix his bugs) is right or
> bad.
>

But what if you could have both? Crash information and stability. Wouldn't
that be the best case?

> It is sounds more and more like wholly war of PASCAL and C.
>

All good ideas are worthy of a holy war...

> If you was not convinced so far I hardly believe you will be convinced
ever.

Yes, and I have failed to convince you of anything... other than maybe to
use a DLL for your translation function.

> If for you 95% stability is enough then fine.
> All though probability theory says that it does not mean you would not get
> into unfortunate 5% N times in a row and then you will have much more
> trouble
> then if you let you program crash on first place and study it.

So while your program crashes repeatedly, mine will log errors in the Event
Viewer... pick your poison.

Cheers,
dan


Vladimir Petter

unread,
Sep 22, 2003, 11:20:55 PM9/22/03
to
Dan,

There is a simplified version for you bellow. For comparison of those two
see my previous emails.
I still think that the first one is hard to use and has problems.
The second one solves most of them so I think it is practical, but (in case
if you missed this)
it is practical only for crashing application on SEH or handling SEH in
__try/__except.
If you have a different goal then it may not be practical for you in this
case you may try to go with
the first way.

Vladimir.

OLD:


#include "eh.h"
#include "exception"
#include "iostream"
#include "process.h"

struct SEH_exception{};

void default_se_translator(unsigned int code, PEXCEPTION_POINTERS ex) {
std::cout << "se_translator throw SEH_exception, SEH code=" << code <<
std::endl;
std::cout.flush();

throw SEH_exception;
}

void bogus_function(){


char *bogus_pointer = NULL;
*bogus_pointer = 'a';
}

int main(int argc, TCHAR* argv[]){
_set_se_translator(default_se_translator);


try{
bogus_class c;
c.sync_exception();
c.assync_exception();
} catch (std::exception &ex) {
std::cout << "main catched " << ex.what() << std::endl;
std::cout.flush();

} catch (SEH_exception &ex) { //catch SEH here. Try to comment out this
handler
std::cout << "main catched SEH_exception" << std::endl;
std::cout.flush();
throw;


} catch (...) {
std::cout << "main catched catch(...)" << std::endl;
std::cout.flush();
}
std::cout << "main finished" << std::endl;
return 0;
}

NEW:

void default_se_translator(unsigned int code, PEXCEPTION_POINTERS ex) {
std::cout << "se_translator throw SEH_exception, SEH code=" << code <<
std::endl;
std::cout.flush();
throw;
}

void bogus_function(){


char *bogus_pointer = NULL;
*bogus_pointer = 'a';
}

int main(int argc, TCHAR* argv[]){
_set_se_translator(default_se_translator);


try{
bogus_class c;
c.sync_exception();
c.assync_exception();
} catch (std::exception &ex) {
std::cout << "main catched " << ex.what() << std::endl;
std::cout.flush();

} catch (...) { //SEH never comes here

Bruno van Dooren

unread,
Sep 23, 2003, 1:56:39 AM9/23/03
to

> Does anyone know how null pointer dereference is handled by *nix
> programmers? Is there and existing idiom? Or is it just, burn baby,
burn!
>
errors are just an integral part of .nix / linux.
this is obvious because there are so much of them, and apparently this has
to be this way
because you are not supposed to solve them. otherwise they would produce
decent error messages.

don't you just love 'error 1 occurred' type messages without any further
explanation.
on the other hand there are error messages such as 'I found no root and i
want to scream!!!!!!!!!'
on one occasion i even encountered the error
'Aaaaaaaaaaaaaaaaaaaaaarrrrrggghhh'. really usefull.

as to null pointer dereference: the application just crashes with a
segmentation fault and
leaves its core dump for examination.

kind regards,
Bruno.


Vladimir Petter

unread,
Sep 23, 2003, 2:53:32 AM9/23/03
to
Dan,

> > - First It would be much better to live in the catch(...) only C++
> > exceptions in the catch block this would make it as safe as it
> > was designed in the C++ standard.
> > - Second some developers do not like __try/__except in some reasons so
> > I thought that VC++ could in general extend language letting handle SEH
> > exceptions
> > in a special block where you have enough information (I am assuming
> > GetExceptionInformation is available there) to make decision.
> >
> I wan't trying to restart that debate. I thought you wanted some sort of
> special attributes on the SEH exceptions so that they were only caught by
> __except.

You've lost me there.

> > I do not want to go again into discussion if letting application crash
> > (from my point it is equal having developer to fix his bugs) is right or
> > bad.
> >
> But what if you could have both? Crash information and stability.
Wouldn't
> that be the best case?

Could you elaborate on this. How would you get there? I should admit I see
you arguing
a lot, but I do not see you clearly express any points so far. Live
everything as is?

> > If you was not convinced so far I hardly believe you will be convinced
> ever.
> Yes, and I have failed to convince you of anything... other than maybe to
> use a DLL for your translation function.

All though I am using it to fix catch(...) (make it not catch SEH). I am not
interested in other
ways to use it.

>
> > If for you 95% stability is enough then fine.
> > All though probability theory says that it does not mean you would not
get
> > into unfortunate 5% N times in a row and then you will have much more
> > trouble
> > then if you let you program crash on first place and study it.
> So while your program crashes repeatedly, mine will log errors in the
Event
> Viewer... pick your poison.

Frequent crashes is not caused by not using catch(...) to handle SEH it is
caused by bugs in software. In my approach I am concern about fixing them as
much as
possible and ASAP so please do not jump to a wrong conclusion. catch(...)
with SEH and
logging does not give you any guaranty that you would not crash badly next
second causing
much more damage to the system.
Actually, if you did not get it from my previous postings, I am even not
arguing against
handling SEH exceptions. One can do it as far as she knows what she is
doing.
But I definitely do not like the way catch(...) works in VC++ (I explained
why).
So it would be more practical if you clearly explain your point of view and
highlight
what you are not agreed with.

Vladimir.


Bo-Staffan Lankinen

unread,
Sep 23, 2003, 6:22:34 AM9/23/03
to
"Craig Powers" <eni...@hal-pc.org> wrote in message
news:3F6F517A...@hal-pc.org...

> The thing is, though, as far as I can see it only ever goes against
> the written word of the standard in situations where undefined behavior
> has occurred, at which point the implementation has license to do
> anything it wants (insert gratuitous comment about formatting your hard
> drive, emailing your boss, or nasal demons here).

No, UB doesn't grant an implementor "license to do anything it wants", that
would be pointless. It can choose to (A) ignore the situation with
unpredictable result or (B) define the behavior. VC++ chooses B, but in a
way that contradicts the defined behavior in the standard. If every
implementor would change the defined behavior in the standard, it would be
impossible to write platform-independent code with a defined behavior, which


defeats the entire purpose of a standard.

> The problem, of course, is that to have gone into the corrupted state,


> your program will have already done something undefined.

No it doesn't. An SE can have been raised to signal an error of some kind.
Even dereferencing a NULL-ptr doesn't invoke UB in VC++, the behavior is
defined and documented. Ofcourse, to continue execution in the event of an
CPU-exception, with the risk of having an expression only partially
evaluated or the exception to occur in a code-block designed to be executed
as an atomic operation (ie compromising the exception safety) can lead to
unpredictable results, but the behavior is defined.

> Even then,
> although catch(...) is unlikely to do the right thing, there are tools
> at your disposal to avoid the problem, most notably _set_se_translator.

This discussion goes beyond the problem that _set_se_translator solves. Can
_set_se_translator guarantee that no SE is inadvertly catched by a
catch(...). AFAIK, no it can't. If an SE, for whatever reasons, is
propagating through my code then I don't want it to be catched by a
catch(...), with the risk of silently compromise the state of the program,
but to have it propagate uncatched, invoking either the debugger or my SEH.
Most of my code is platform independent, written with the standard behavior
in mind, that means it wasn't designed to handle SEs arbitrarily propagating
through the code. It might very well recover gracefully from an SE but that
isn't generally true and how could I fix that problem if I don't know it has
happened?

> If you run into problems with catch(...), your problems are more
> fundamental than neglect of exception safety.

I don't get your point or you don't know what the concept of exception
safety means. If that's the case, here's a link explaining it.

www.boost.org/more/generic_exception_safety.html

Bo-Staffan


Daniel James

unread,
Sep 23, 2003, 8:26:10 AM9/23/03
to
In article news:<#LwFSLTg...@TK2MSFTNGP10.phx.gbl>, Dan Daly
wrote:

> > The exception /conditions/ are the same (bad pointer), but the
> > actual exceptions are different.
>
> Semantically they are the same. IMHO, this is all that really
> matters.

No, they're not. Maybe they could be, but as things are implemented
they're not. In almost all senses SEH exceptions and C++ exceptions
are syntactically and sematically distinct BUT catch(...) works on
both of them.

The problem is that MS have made a half-hearted attempt to integrate
handling of SEH exceptions into the C++ language, but haven't
actually provided enough flexibility for that integration to be
useful. It's nice that automatic variables are properly destroyed as
an SEH exception unwinds the stack, but not so nice that it it isn't
possible to handle specific SEH exceptions within a C++ catch block.

That is, you can't write:

try
{
foo();
}
catch( const MyException& eMine )
{
// handle my own exception hierarchy
...
}
catch( const SEHException& eSEH )
{
if( GetExceptionCode()== ....
// etc ...
}
catch( ... )
{
// handle anything else
...
}

Instead, you have to have both a __try/__except block to catch any
SEH exception and also a try/catch block to catch any C++ exceptions
thrown by foo(). You have to handle these differently because throw
and RaiseException work in different ways and result in different
(and largely incompatible) execution states. It's only when you
don't care what the exception was (the catch(...) case) that it's
possible to ignore the excution state and just truncate the stack.

MS *could* have placed extra information on the stack at the point
of a throw and/or a RaiseException so that the code generated for
the compiler by catch() could test for the exception type being
caught and branch to a handler of an appropriate type. This might be
useful in some cases, but would involve extra code and extra work at
runtime, and so would violate the C++ rule that you don't pay for
what you don't use.

If you need to be able to handle both SEH and C++ exceptions arising
from the same block of code (and I would argue that there should
rarely be the need) then you should bite the bullet and code to
catch them separately.

Cheers,
Daniel.


Vladimir Petter

unread,
Sep 23, 2003, 12:35:20 PM9/23/03
to
Sorry, there were several error caused by rush in previose posting.
There is a fixed version:
//OLD:

#include "windows.h"

#include "eh.h"

#include "exception"

#include "iostream"

#include "process.h"

struct SEH_exception{};

void default_se_translator(unsigned int code, PEXCEPTION_POINTERS ex){
std::cout << "se_translator throw SEH_exception, SEH code=" << code
<<std::endl;
std::cout.flush();

throw SEH_exception();
}

void bogus_function(){
char *bogus_pointer = NULL;
*bogus_pointer = 'a';
}

int main(int argc, TCHAR* argv[]){
_set_se_translator(default_se_translator);
try{

bogus_function();


} catch (std::exception &ex) {
std::cout << "main catched " << ex.what() << std::endl;
std::cout.flush();
} catch (SEH_exception &ex) { //catch SEH here. Try to comment out this
handler
std::cout << "main catched SEH_exception" << std::endl;
std::cout.flush();
throw;
} catch (...) {
std::cout << "main catched catch(...)" << std::endl;
std::cout.flush();
}
std::cout << "main finished" << std::endl;
return 0;
}

// NEW

#include "windows.h"

#include "eh.h"
#include "exception"
#include "iostream"
#include "process.h"

void default_se_translator(unsigned int code, PEXCEPTION_POINTERS ex) {


std::cout << "se_translator throw SEH_exception, SEH code=" << code
<<std::endl;
std::cout.flush();
throw;
}

void bogus_function(){
char *bogus_pointer = NULL;
*bogus_pointer = 'a';
}

int main(int argc, TCHAR* argv[]){
_set_se_translator(default_se_translator);
try{

bogus_function();

Dan Daly

unread,
Sep 23, 2003, 7:13:13 PM9/23/03
to
Vladimir,

> > > I do not want to go again into discussion if letting application
crash
> > > (from my point it is equal having developer to fix his bugs) is right
or
> > > bad.
> > >
> > But what if you could have both? Crash information and stability.
> Wouldn't
> > that be the best case?
> Could you elaborate on this. How would you get there? I should admit I see
> you arguing
> a lot, but I do not see you clearly express any points so far. Live
> everything as is?
>

Yes. And I believe I have expressed that repeatedly. As this thread has
progressed, I have come to realize that we are starting with different goals
in mind. My experiences with these issues were shaped over a four year
period, when I worked on a Telephony project that required a high degree of
fault tolerance. Myself and a small group of engineers stuck our necks out
and convinced the VP that we could develop a robust system on NT. We did it
by employing a strict design policy that included exceptions, logging,
tracing, etc. That code was rock solid and I have never worked on code
since that could be fixed as quickly... due in large part to our ability to
catch *all* exceptions.

If I have appeared argumentative, it is because most of your arguments,
while theoritically possible, did not exist for us. In other words, in
actual practice, we never experienced the catastropes (wild crashes,
ambigous tranlators, etc.) that you seem so concerned about.

Some of our rules were:
1) Never crash! Wrap all external interfaces so that exceptions cannot
escape.
2) Log all API failures, then throw.
3) Log all catches, using unique error code to provide informational
message.
4) When logging a failure. Provide some useful information on how to fix
it. This often requires iterations.
5) Log all data to the Event Viewer as Error, Information, or Warning.
6) All excpetions should have a unique code.
7) All codes are grouped via module.
8) COM objects never let an exception escape. Always return an HRESULT.
9) Use Tracing on function entry and exit. This is off by default, but an
be turned on without restarting application.
10) Do not use exceptions for regular, likely to occur under normal
circumstances, non-exceptional errors, i.e., bad password, file not found,
etc... That is, do not use exceptions as merely another way of returning
errors.

Of course, all of this worked, in part, because we started this project from
the ground up. I know that the code you are working on is not as friendly.
However, I do believe that employing these same desing principles would
probably have similar rusults for you - though it may take some time to
really see the pay off.

I think we have exhaused everyone else on the list, so if you want to
continue, let's do it off line.

Cheers,
dan

Dan Daly

unread,
Sep 23, 2003, 7:29:46 PM9/23/03
to
Vlad,

Thanks for putting all this together! So I see that in the "new" version
you do not need to catch SEH_exception... yes, much better I agree... but I
still think you are heading down the wrong road... but we will just have to
agree to disagree...

On the other hand, if you have tens of thousands of lines of code that use
(...) to hide SEH's, then using the translator as such is a - can I say
it? - elegant way of quickly generating the crash dumps you need to fix
problems... good job.

dan


"Vladimir Petter" <vla...@hotmail.com> wrote in message

news:Oj3L1Cfg...@TK2MSFTNGP09.phx.gbl...

Craig Powers

unread,
Sep 24, 2003, 3:46:06 PM9/24/03
to
Bo-Staffan Lankinen wrote:
>
> "Craig Powers" <eni...@hal-pc.org> wrote in message
> news:3F6F517A...@hal-pc.org...

> > If you run into problems with catch(...), your problems are more


> > fundamental than neglect of exception safety.
>
> I don't get your point or you don't know what the concept of exception
> safety means. If that's the case, here's a link explaining it.
>
> www.boost.org/more/generic_exception_safety.html

I think I wasn't quite clear enough. It's not problems with catch(...)
in general I was referring to, it's problems with the particular
feature of catch(...) under discussion.

My point was that if you run into problems with this undermining
exception safety, you really have more fundamental problems. As a
general rule, anything in user code that would generate an SE is a
bug.

Bo-Staffan Lankinen

unread,
Sep 25, 2003, 7:36:13 AM9/25/03
to
> I think I wasn't quite clear enough. It's not problems with catch(...)
> in general I was referring to, it's problems with the particular
> feature of catch(...) under discussion.
>
> My point was that if you run into problems with this undermining
> exception safety, you really have more fundamental problems. As a
> general rule, anything in user code that would generate an SE is a
> bug.

Ofcourse it's a bug. The only "fundamental problem" might be that you have
designed your code according to the standard behavior, which means that when
the catch(...) is run, the application should be in a defined state, but in
fact it isn't.

I only feel like I'm repeating myself and I don't think we are getting
anywhere with this discussion but in a way that really doesn't matter
because both Ronald and Brandon has stated that the next version of VC++
will offer the standard behavior and that is good enough for me.

Bo-Staffan


0 new messages