By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,157 Members | 1,001 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,157 IT Pros & Developers. It's quick & easy.

C++ exception handling is defective

P: n/a
The simplicity of stack unraveling of C++ is not without defective
consequences. The following article points to C++ examples showing the
defects. An engineer aware of defects can avoid hard-to-find bugs.

http://distributed-software.blogspot...defective.html

Regards,
zo****@ZHMicro.com
http://www.zhmicro.com
http://distributed-software.blogspot.com
http://groups-beta.google.com/group/...Z?lnk=la&hl=en

Jan 9 '07 #1
Share this Question
Share on Google+
132 Replies


P: n/a
Zorro wrote:
The simplicity of stack unraveling of C++ is not without defective
consequences. The following article points to C++ examples showing the
defects. An engineer aware of defects can avoid hard-to-find bugs.

http://distributed-software.blogspot...defective.html

None of the C++ examples in the PDF linked from there is actually using
exception handling. They all invoke undefined behavior. They don't show a
defect in C++'s exception handling, but rather a lack of the author's
understanding of C++.

BTW: Those examples are also using the <iostream.hheader that has been
outdated in C++ for about 10 years now and has actually never even been
part of the C++ Standard.

Jan 9 '07 #2

P: n/a
Rolf Magnus wrote:
Zorro wrote:

>>The simplicity of stack unraveling of C++ is not without defective
consequences. The following article points to C++ examples showing the
defects. An engineer aware of defects can avoid hard-to-find bugs.


http://distributed-software.blogspot...defective.html

None of the C++ examples in the PDF linked from there is actually using
exception handling. They all invoke undefined behavior. They don't show a
defect in C++'s exception handling, but rather a lack of the author's
understanding of C++.
Agreed, I wonder which compiler and environment produced the results
claimed.
BTW: Those examples are also using the <iostream.hheader that has been
outdated in C++ for about 10 years now and has actually never even been
part of the C++ Standard.
Not to mention idiomatic C (void).

--
Ian Collins.
Jan 9 '07 #3

P: n/a
"Zorro" <zo****@comcast.netwrote in message
news:11**********************@o58g2000hsb.googlegr oups.com...
The simplicity of stack unraveling of C++ is not without defective
consequences. The following article points to C++ examples showing the
defects. An engineer aware of defects can avoid hard-to-find bugs.

http://distributed-software.blogspot...ing-is-defecti
ve.html

The fact that the code samples use <iostream.hand not <iostreamsuggests that
a very old compiler was used to demonstrate the supposed exception bugs. If the
code is updated for <iostreamand the divisions by zero are replaced by throws
(/0 causes undefined behaviour) and a more recent compiler is used, I think
you'll find that the destructor is indeed called when the stack is unwound. It
looks like a defective compiler rather than a defective language.

DW
Jan 9 '07 #4

P: n/a
David W wrote:
The fact that the code samples use <iostream.hand not <iostream>
suggests that a very old compiler was used to demonstrate the supposed
exception bugs. If the code is updated for <iostreamand the divisions by
zero are replaced by throws (/0 causes undefined behaviour) and a more
recent compiler is used, I think you'll find that the destructor is indeed
Better say a correct compiler. I have seen Borland Kilyx failing to call
destructors in cases similar to that (but correct). I even asked here if
the code has some error I failed to see, if I remember well. And Borland
acknowledged the bug, but failed to provide a solution (at least during the
time that I have the patience to keep checking).

--
Salu2
Jan 10 '07 #5

P: n/a

Zorro wrote:
The simplicity of stack unraveling of C++ is not without defective
consequences. The following article points to C++ examples showing the
defects. An engineer aware of defects can avoid hard-to-find bugs.

http://distributed-software.blogspot...defective.html

Regards,
zo****@ZHMicro.com
http://www.zhmicro.com
http://distributed-software.blogspot.com
http://groups-beta.google.com/group/...Z?lnk=la&hl=en
This is a common reply to several comments, respectfully.

1. The use of one or another header file is cosmetic for this example.
2. When you say a correct compiler will do better, please specify the
compiler.
3. Division by 0 happens at system level and is not necessary to turn
it into a throw.
4. For this example, the compiler is Microsoft Visual C++ version 6.
5. The defect is in the technique used. Of course it can be corrected.
Show me a compiler that has in fact corrected this problem. The point
is that, it takes a great deal beyond plain stack unraveling to correct
this problem.
6. If you are not familiar with the concept, and do not see the real
issue, avoid revealing it.

With respect, the best way I could present my response.

Regards,
zo****@ZHMicro.com
http://www.zhmicro.com
http://distributed-software.blogspot.com
http://groups-beta.google.com/group/...Z?lnk=la&hl=en

Jan 10 '07 #6

P: n/a
Zorro wrote:
Zorro wrote:
>>The simplicity of stack unraveling of C++ is not without defective
consequences. The following article points to C++ examples showing the
defects. An engineer aware of defects can avoid hard-to-find bugs.

http://distributed-software.blogspot...defective.html

Regards,
zo****@ZHMicro.com
http://www.zhmicro.com
http://distributed-software.blogspot.com
http://groups-beta.google.com/group/...Z?lnk=la&hl=en


This is a common reply to several comments, respectfully.

1. The use of one or another header file is cosmetic for this example.
It may or may not be cosmetic, but is asking for flak.
2. When you say a correct compiler will do better, please specify the
compiler.
Changing you example to standard C++:

#include <iostream>

struct simple
{
int s;
simple() { s = 5;}
~simple(void) {std::cout << "Destructor ..." << std::endl;}
};

int main(){
int i = 1, j = 0;
try {
simple spl;
throw 0;
}
catch(...) {
std::cout << "Caught it" << std::endl;
}
std::cout << "Finishing" << std::endl;
return 0;
}

any compiler should give the correct result. If not, it is broken.
3. Division by 0 happens at system level and is not necessary to turn
it into a throw.
Then why use it in your examples?
4. For this example, the compiler is Microsoft Visual C++ version 6.
Old and not very compliant.
5. The defect is in the technique used. Of course it can be corrected.
Show me a compiler that has in fact corrected this problem. The point
is that, it takes a great deal beyond plain stack unraveling to correct
this problem.
Show me one that exibits it.
6. If you are not familiar with the concept, and do not see the real
issue, avoid revealing it.
Which concept?

--
Ian Collins.
Jan 10 '07 #7

P: n/a
Zorro wrote:
>
Zorro wrote:
>The simplicity of stack unraveling of C++ is not without defective
consequences. The following article points to C++ examples showing the
defects. An engineer aware of defects can avoid hard-to-find bugs.

http://distributed-software.blogspot...defective.html
>>
Regards,
zo****@ZHMicro.com
http://www.zhmicro.com
http://distributed-software.blogspot.com
http://groups-beta.google.com/group/...Z?lnk=la&hl=en

This is a common reply to several comments, respectfully.

1. The use of one or another header file is cosmetic for this example.
2. When you say a correct compiler will do better, please specify the
compiler.
Your compiler did just fine. The output you present is a perfectly valid
output for the program.
3. Division by 0 happens at system level and is not necessary to turn
it into a throw.
The problem with the division by 0 is that it simply is undefined behavior
according to the standard. The language specification places no
requirements upon the observable behavior of any program that executed a
division by 0. Therefore, the output you attribute to incorrect handling of
exceptions is a perfectly valid output for your program (and so would be
any other).

What puts your program into an inconsistent state is not some exception but
the division by 0, which is UB.
4. For this example, the compiler is Microsoft Visual C++ version 6.
5. The defect is in the technique used. Of course it can be corrected.
The defect lies in the undefined behavior.
Show me a compiler that has in fact corrected this problem. The point
is that, it takes a great deal beyond plain stack unraveling to correct
this problem.
Your program does not illustrate problem with stack unravelling. It
illustrates that all bets are off once you have undefined behavior.
6. If you are not familiar with the concept, and do not see the real
issue, avoid revealing it.
Huh?
Best

Kai-Uwe Bux
Jan 10 '07 #8

P: n/a

Kai-Uwe Bux wrote:
Zorro wrote:

Zorro wrote:
The simplicity of stack unraveling of C++ is not without defective
consequences. The following article points to C++ examples showing the
defects. An engineer aware of defects can avoid hard-to-find bugs.

http://distributed-software.blogspot...defective.html
>
Regards,
zo****@ZHMicro.com
http://www.zhmicro.com
http://distributed-software.blogspot.com
http://groups-beta.google.com/group/...Z?lnk=la&hl=en
This is a common reply to several comments, respectfully.

1. The use of one or another header file is cosmetic for this example.
2. When you say a correct compiler will do better, please specify the
compiler.

Your compiler did just fine. The output you present is a perfectly valid
output for the program.
3. Division by 0 happens at system level and is not necessary to turn
it into a throw.

The problem with the division by 0 is that it simply is undefined behavior
according to the standard. The language specification places no
requirements upon the observable behavior of any program that executed a
division by 0. Therefore, the output you attribute to incorrect handling of
exceptions is a perfectly valid output for your program (and so would be
any other).

What puts your program into an inconsistent state is not some exception but
the division by 0, which is UB.
4. For this example, the compiler is Microsoft Visual C++ version 6.
5. The defect is in the technique used. Of course it can be corrected.

The defect lies in the undefined behavior.
Show me a compiler that has in fact corrected this problem. The point
is that, it takes a great deal beyond plain stack unraveling to correct
this problem.

Your program does not illustrate problem with stack unravelling. It
illustrates that all bets are off once you have undefined behavior.
6. If you are not familiar with the concept, and do not see the real
issue, avoid revealing it.

Huh?
Best

Kai-Uwe Bux
Kai-Uwe, division by 0 is undefined just as trying to deref a null
pointer. These are exceptional cases that can happen. Simply calling
them (undefined behavior) does not help in anyway. Are you saying that,
if one of these cases, or many similar ones, happens the program should
necessarily terminate? Then what is the point of having an exception
mechanism?
Yes, the output is correct in accordance to C++ standard. But, is it
acceptable just because that is how it is?

Thanks for your contribution as it brought one more point to attention.

Regards,
zo****@ZHMicro.com
http://www.zhmicro.com
http://distributed-software.blogspot.com
http://groups-beta.google.com/group/...Z?lnk=la&hl=en

Jan 10 '07 #9

P: n/a

Ian Collins wrote:
Zorro wrote:
Zorro wrote:
>The simplicity of stack unraveling of C++ is not without defective
consequences. The following article points to C++ examples showing the
defects. An engineer aware of defects can avoid hard-to-find bugs.

http://distributed-software.blogspot...defective.html

Regards,
zo****@ZHMicro.com
http://www.zhmicro.com
http://distributed-software.blogspot.com
http://groups-beta.google.com/group/...Z?lnk=la&hl=en

This is a common reply to several comments, respectfully.

1. The use of one or another header file is cosmetic for this example.

It may or may not be cosmetic, but is asking for flak.
2. When you say a correct compiler will do better, please specify the
compiler.

Changing you example to standard C++:

#include <iostream>

struct simple
{
int s;
simple() { s = 5;}
~simple(void) {std::cout << "Destructor ..." << std::endl;}
};

int main(){
int i = 1, j = 0;
try {
simple spl;
throw 0;
}
catch(...) {
std::cout << "Caught it" << std::endl;
}
std::cout << "Finishing" << std::endl;
return 0;
}

any compiler should give the correct result. If not, it is broken.
3. Division by 0 happens at system level and is not necessary to turn
it into a throw.

Then why use it in your examples?
4. For this example, the compiler is Microsoft Visual C++ version 6.

Old and not very compliant.
5. The defect is in the technique used. Of course it can be corrected.
Show me a compiler that has in fact corrected this problem. The point
is that, it takes a great deal beyond plain stack unraveling to correct
this problem.

Show me one that exibits it.
6. If you are not familiar with the concept, and do not see the real
issue, avoid revealing it.
Which concept?

--
Ian Collins.
Ian, the stream library for output is not the issue. I only tried to
write less because that was not the point. However, you are replacing
division by 0 with a throw. What the example is speaking of is about
exceptions that can happen without you throwing them. Although I am not
saying that your version does not fail.

The concept I am referring to is exceptional events that can happen as
your program executes. For instance, the operating system does not die
on a division by 0. It simply aborts your program. Thus, the point is
that, a C++ compiler's run-time library must sense and report such
events to your program so you can do something about them. Indeed, in
this example the compiler does report. The problem is the way the
run-time library is handling the recovery, known as stack unraveling.
One needs to do a few more things as housekeeping besides popping the
stack, and passing the exception to the next call.

Thanks for your comment.

Regards,
zo****@ZHMicro.com
http://www.zhmicro.com
http://distributed-software.blogspot.com
http://groups-beta.google.com/group/...Z?lnk=la&hl=en

Jan 10 '07 #10

P: n/a
Zorro wrote:
>
Kai-Uwe Bux wrote:
>Zorro wrote:
>
Zorro wrote:
The simplicity of stack unraveling of C++ is not without defective
consequences. The following article points to C++ examples showing the
defects. An engineer aware of defects can avoid hard-to-find bugs.

http://distributed-software.blogspot...defective.html
>>
Regards,
zo****@ZHMicro.com
http://www.zhmicro.com
http://distributed-software.blogspot.com
http://groups-beta.google.com/group/...Z?lnk=la&hl=en
[snip]
2. When you say a correct compiler will do better, please specify the
compiler.

Your compiler did just fine. The output you present is a perfectly valid
output for the program.
3. Division by 0 happens at system level and is not necessary to turn
it into a throw.

The problem with the division by 0 is that it simply is undefined
behavior according to the standard. The language specification places no
requirements upon the observable behavior of any program that executed a
division by 0. Therefore, the output you attribute to incorrect handling
of exceptions is a perfectly valid output for your program (and so would
be any other).

What puts your program into an inconsistent state is not some exception
but the division by 0, which is UB.
[snip]
>
Kai-Uwe, division by 0 is undefined just as trying to deref a null
pointer. These are exceptional cases that can happen. Simply calling
them (undefined behavior) does not help in anyway. Are you saying that,
if one of these cases, or many similar ones, happens the program should
necessarily terminate? Then what is the point of having an exception
mechanism?
The try-throw-catch mechanism is not meant to handle those cases. I have
outlined the benefit of try-throw-catch in the following post:

http://groups.google.com/group/comp....08bdf6553abbc6

Yes, the output is correct in accordance to C++ standard. But, is it
acceptable just because that is how it is?
To me, the current state of affairs with regard to dereferencing a null
pointer or dividing by 0 is acceptable. C++ has basic types that make very
little guarantees. If you want stronger predictability, you should define
simple wrapper classes that provide the additional guarantees. For
instance, I never use pointers directly. Instead I have a simple pointer
wrapper class. It defines operator* so that an assert() is made to catch
dereferencing 0. I also have a wrapper template for the floating point
types (it allows me to overload operator== to do sloppy comparison). This
also catches division by 0.

Also note that this solution is more flexible: I use assert() to catch those
instances, since I consider them bugs. Others may feel that division by 0
is not so much a bug of the program but something due to faulty input. From
that point of view throwing an exception may be more appropriate. I would
not want the language specification make that decision for me.
Best

Kai-Uwe Bux
Jan 10 '07 #11

P: n/a
Zorro wrote:
Ian Collins wrote:
>Zorro wrote:
>>Zorro wrote:

The simplicity of stack unraveling of C++ is not without defective
consequences. The following article points to C++ examples showing the
defects. An engineer aware of defects can avoid hard-to-find bugs.

http://distributed-software.blogspot...defective.html

Regards,
zo****@ZHMicro.com
http://www.zhmicro.com
http://distributed-software.blogspot.com
http://groups-beta.google.com/group/...Z?lnk=la&hl=en

This is a common reply to several comments, respectfully.

1. The use of one or another header file is cosmetic for this example.
It may or may not be cosmetic, but is asking for flak.
>>2. When you say a correct compiler will do better, please specify the
compiler.
Changing you example to standard C++:

#include <iostream>

struct simple
{
int s;
simple() { s = 5;}
~simple(void) {std::cout << "Destructor ..." << std::endl;}
};

int main(){
int i = 1, j = 0;
try {
simple spl;
throw 0;
}
catch(...) {
std::cout << "Caught it" << std::endl;
}
std::cout << "Finishing" << std::endl;
return 0;
}

any compiler should give the correct result. If not, it is broken.
>>3. Division by 0 happens at system level and is not necessary to turn
it into a throw.
Then why use it in your examples?
>>4. For this example, the compiler is Microsoft Visual C++ version 6.
Old and not very compliant.
>>5. The defect is in the technique used. Of course it can be corrected.
Show me a compiler that has in fact corrected this problem. The point
is that, it takes a great deal beyond plain stack unraveling to correct
this problem.
Show me one that exibits it.
>>6. If you are not familiar with the concept, and do not see the real
issue, avoid revealing it.
Which concept?

--
Ian Collins.

Ian, the stream library for output is not the issue. I only tried to
write less because that was not the point. However, you are replacing
division by 0 with a throw. What the example is speaking of is about
exceptions that can happen without you throwing them. Although I am not
saying that your version does not fail.

The concept I am referring to is exceptional events that can happen as
your program executes. For instance, the operating system does not die
on a division by 0. It simply aborts your program. Thus, the point is
that, a C++ compiler's run-time library must sense and report such
events to your program so you can do something about them. Indeed, in
this example the compiler does report. The problem is the way the
run-time library is handling the recovery, known as stack unraveling.
One needs to do a few more things as housekeeping besides popping the
stack, and passing the exception to the next call.
So you are actually talking about two separate issues:

1) C++ doesn't throw properly upon divide-by-zero
2) Objects out of scope are not properly destroyed upon divide-by-zero

C++ exception is meant for reporting exceptional circumstances, but for
detecting it. So it is your responsibility to detect and throw properly.

C++ could have properly throw an exception when you try to divide an int
by zero. However, this will put up a significant performance penalty
that not everyone is comfortable with. Alternatively, you can simple
test the divident and throw your own exception:

if (j == 0)
throw divide_by_zero();

i /= j;

This is easy, and you can always create your own type that acts in every
way like an int but throws properly when divided by a zero. So you have
got choices to choose from.

class safe_int
{
int repr;

// ...
};

safe_int operator/=(safe_int lhs, int rhs)
{
if (rhs == 0) throw divide_by_zero();
lhs.repr /= rhs;
return lhs;
}
Once 1) is solved (by using a test or using your own int-like class),
issue 2) is easy. Since the division is no longer a UB, objects out of
scope are guaranteed to be destroyed properly.

Oh btw, please please stop using old compilers!

Regards,
Ben
>
Thanks for your comment.

Regards,
zo****@ZHMicro.com
http://www.zhmicro.com
http://distributed-software.blogspot.com
http://groups-beta.google.com/group/...Z?lnk=la&hl=en
Jan 10 '07 #12

P: n/a
Zorro a écrit :
Yes, the output is correct in accordance to C++ standard. But, is it
acceptable just because that is how it is?
Well this is how C++ has been defined by "philosophy" (no overhead in
generated code, i.e. no test when dividing to check for 0 division so no
exception raised)

I suggest you to look at the ADA language if you want an exception to be
raised when dividing by 0 (I mean without having to throw it yourself)
or when accessing an invalid index in a array or even when there is an
overflow.

J.

Thanks for your contribution as it brought one more point to attention.

Regards,
zo****@ZHMicro.com
http://www.zhmicro.com
http://distributed-software.blogspot.com
http://groups-beta.google.com/group/...Z?lnk=la&hl=en
Jan 10 '07 #13

P: n/a
Zorro wrote:
Ian Collins wrote:
>>
Which concept?
First, please reply inline and trim signatures.
>
Ian, the stream library for output is not the issue. I only tried to
write less because that was not the point. However, you are replacing
division by 0 with a throw. What the example is speaking of is about
exceptions that can happen without you throwing them. Although I am not
saying that your version does not fail.
Then you aren't talking about exceptions in the C++ sense of the term.
You are talking about events that are beyond the standard.
The concept I am referring to is exceptional events that can happen as
your program executes. For instance, the operating system does not die
on a division by 0. It simply aborts your program. Thus, the point is
that, a C++ compiler's run-time library must sense and report such
events to your program so you can do something about them. Indeed, in
this example the compiler does report. The problem is the way the
run-time library is handling the recovery, known as stack unraveling.
One needs to do a few more things as housekeeping besides popping the
stack, and passing the exception to the next call.
It any not be possible for this to happen on many platforms without
checking each and every memory access or operation, which would be
intolerable.

--
Ian Collins.
Jan 10 '07 #14

P: n/a
Zorro wrote:
Kai-Uwe, division by 0 is undefined just as trying to deref a null
pointer. These are exceptional cases that can happen. Simply calling
them (undefined behavior) does not help in anyway.
It helps in some (other than yours) situations. You see, one design goals of
C++ is to not pay for something you don't use/need. While _you_ would like
the language to check for division by 0 and throw some exception in that
case, others (ME for example) would NOT like it as it will make every
devision in my programs slower for a corner case that I know I never reach.
Thus infriging on my right to have a faster program and on the principle do
not pay a price for what you don't need.

However, at the same time, for people with _your_ needs overloading
operator/ and company (or other wrapper solution) can be implemented:
1. easily
2. it does what you need without making the rest (that don't need it) pay
for what you need

So what we have now with the current C++ is a win/win situation. Why fix it
if it works ?
Are you saying that,
if one of these cases, or many similar ones, happens the program should
necessarily terminate?
No, UB doesn't mean terminate, it's just undefined what it happens. That is
you shouldn't do it and if you are unsure (or you KNOW that you might be
doing it) add checks to avoid it. But for the people (and cases) that are
100% sure it will never happen there are no checks needed thus we have less
overhead when we don't need it.
Then what is the point of having an exception
mechanism?
To offer syntax and semantics that make it easy to decouple the place of
error detection with the place of error handling. Also (because it supports
ordinary types and selects the specific type throwed) to make it flexible
in reporting information about the error. But certainly I don't think it
was ment to be used to signal some rare conditions by adding checks where
not all need them and where they can be added easily by those who need
them.

Take another case for example, why doesn't C++ arrays subscript operator
(which are the C arrays actually) and even the standard library containers
(such as vector::operator[]) do not check for range and throw something if
the range is out of bounds ? It is EXACTLY the same reason (however, notice
that std::vector provides .at() that does check I think so you see, you
have a choice).
Yes, the output is correct in accordance to C++ standard. But, is it
acceptable just because that is how it is?
For the reasons explained above (which apply to dozens other such decisions
in the C++ standar) YES YES YES! :)

--
Dizzy
http://dizzy.roedu.net

Jan 10 '07 #15

P: n/a
Zorro wrote:
>
Zorro wrote:
>The simplicity of stack unraveling of C++ is not without defective
consequences. The following article points to C++ examples showing the
defects. An engineer aware of defects can avoid hard-to-find bugs.

http://distributed-software.blogspot...defective.html
>>
Regards,
zo****@ZHMicro.com
http://www.zhmicro.com
http://distributed-software.blogspot.com
http://groups-beta.google.com/group/...Z?lnk=la&hl=en

This is a common reply to several comments, respectfully.

1. The use of one or another header file is cosmetic for this example.
If you are talking about what you consider to be defects in the Standard C++
language, at least you have to use that. Otherwise, your credibility is
gone at that point already.
2. When you say a correct compiler will do better, please specify the
compiler.
The compiler's output _is_ correct, just as any other C++ compiler's is.
3. Division by 0 happens at system level and is not necessary to turn
it into a throw.
Exactly. Anything can happen. You just used one specific compiler that
happens to throw an exception in this case and seems to have a bug. That's
not a proper basis to conclude that there must be a flaw in C++'s exception
handling. On my compiler, an exception is never even thrown by that
program, and C++ doesn't require or even suggest it. So your code basically
has nothing to do with C++ exceptions. It only has to with the behavior of
one specific compiler.
4. For this example, the compiler is Microsoft Visual C++ version 6.
Wow, that's an old one. It's not really known for its standard compliance,
but who's to blame it? AFAIK, that compiler is even older than the
standard. It's ancient.
5. The defect is in the technique used. Of course it can be corrected.
It is in the implementation of the compiler and your assumptions, not in the
C++ standard.
Show me a compiler that has in fact corrected this problem. The point
is that, it takes a great deal beyond plain stack unraveling to correct
this problem.
6. If you are not familiar with the concept, and do not see the real
issue, avoid revealing it.
Familiar with what concept? You don't seem familiar with the concept of
undefined behavior.

Jan 10 '07 #16

P: n/a

Zorro skrev:
The simplicity of stack unraveling of C++ is not without defective
consequences. The following article points to C++ examples showing the
defects. An engineer aware of defects can avoid hard-to-find bugs.

http://distributed-software.blogspot...defective.html
You use a very old (from before the C-standard) C++ compiler, write a
program that includes non-standard headers and has undefined behavior
and complain that the output is not what you expected.
This makes the statement "an engineer aware of defects can avoid
hard-to-find bugs" funny in a very sad way.
I hope you can do better than that!

/Peter

Jan 10 '07 #17

P: n/a
On 9 Jan 2007 22:31:06 -0800, "Zorro" wrote:
>division by 0 is undefined just as trying to deref a null
pointer. These are exceptional cases that can happen. Simply calling
them (undefined behavior) does not help in anyway.
From K&R B9:
"The header <signal.hprovides facilities for handling exceptional
conditions that arise during execution, such as an inerrupt signal
from an external source or an error in execution.
....
SIGFPE arithmetic error, e.g., zero devide or overflow
....
SIGSEGV illegal storage access, e.g., access outside memory limits"

Jan 10 '07 #18

P: n/a
On Jan 10, 6:39 am, "Zorro" <zor...@comcast.netwrote:
This is a common reply to several comments, respectfully.

3. Division by 0 happens at system level and is not necessary to turn
it into a throw.
As others have pointed out, this is not an exception. However that does
not mean that there does not exist ways to handle it, on a
POSIX-compatible system you can install a signal-handler for the SIGFPE
(floating-point exception signal), though you always run the risk of
getting a signal for some other kind of exception*, though they are not
that common (they usually terminate the app).

* When I say exception I don't mean a C++ exception but rather a CPU
trap exception.

--
Erik Wikström

Jan 10 '07 #19

P: n/a
Zorro wrote:
1. The use of one or another header file is cosmetic for this example.
Is not. In several compilers mixing standard headers and pre-standard ones
is not supported.
5. The defect is in the technique used. Of course it can be corrected.
Show me a compiler that has in fact corrected this problem.
The problem is in your code, not in the compiler. Dividing by zero you
invoke undefined behaviour. What your compiler does in that situation, you
must check what your compiler documentation does, and blame his authors if
what you see contradicts his documentation. From the standard point of
view, no matter what it does, is undefined.

--
Salu2
Jan 10 '07 #20

P: n/a
Zorro wrote:
The concept I am referring to is exceptional events that can happen as
your program executes. For instance, the operating system does not die
on a division by 0. It simply aborts your program.
What the operating system does has nothing to do with the issue.
Thus, the point is that, a C++ compiler's run-time library must sense and
report such events to your program so you can do something about them.
The point is that all compilers must do what you want just because you like
it that way? If not, there are tons of books and other resources that
explains the reasons for the design decisions of the C++ language.

--
Salu2
Jan 10 '07 #21

P: n/a
Hello!

Zorro wrote:
The simplicity of stack unraveling of C++ is not without defective
consequences. The following article points to C++ examples showing the
defects. An engineer aware of defects can avoid hard-to-find bugs.

http://distributed-software.blogspot...defective.html
I've read this thread, as well as your blog article and referenced
document (which seems to be plugging your Z++), and it seems you're
misunderstanding /why/ the behaviour of division by zero is undefined.

My guess is that the rationale behind it being undefined is something
like the following.

When a processor encounters division by zero, it may well throw an
exception (*not* a C++ exception), complain in some other way, ignore
it, or do something else. What it does depends on the processor. But,
whatever it is, it's beyond the scope of the C++ standard, because the
C++ standard is not there to define such processor behaviour.

If a processor somehow reports division by zero to, say, an operating
system, then that operating system may well respond by sending a signal
to the relevant program, terminating execution of that program, ignoring
it, or doing something else. What it does depends on the operating
system. But, whatever it is, it's beyond the scope of the C++ standard,
because the C++ standard is not there to define such operating system
behaviour.

If the C++ standard was to specify behaviour for division by zero, then
since the processor's behaviour and operating system's behaviour are
beyond the scope of the C++ standard, such specified behaviour may well
have to be implemented in such a way as to prevent the division by zero
from actually occurring in the first place. That would impose often
unnecessary and unwanted overheads. C++ just isn't that sort of language.

Indeed, there are a great many unsafe things that C++ allows programmers
to do. There are unsafe things that C++ allows programmers to do
without even throwing C++ exceptions when they're done. Instead, C++
provides mechanisms for use /when the programmer wants or needs them./
It's the programmer's responsibility to write safe code, /not/ C++
itself. So, C++ provides exception mechanisms /without/ imposing them
on the programmer. If the programmer needs well-behaved exception
handling, the programmer can then use the exception mechanisms provided
accordingly. That's the kind of language that C++ is.

So, if, when doing a division, there's the real (though hopefully
exceptional) possibility of it being a division by zero, the thing to do
is to do that division within a try block, checking for division by zero
before doing the division, and throwing an exception if it would be
division by zero. This could, of course, be wrapped up in your own
number class. No need to change the language itself.

:-)

--
Simon G Best
What happens if I mention Leader Kibo in my .signature?
Jan 10 '07 #22

P: n/a
IR
Zorro wrote:
5. The defect is in the technique used. Of course it can be
corrected. Show me a compiler that has in fact corrected this
problem. The point is that, it takes a great deal beyond plain
stack unraveling to correct this problem.
Basically, you're just saying that RAII in C++ is broken.
This is a tough statement, you're gonna have hard time proving it...

Incidentally, as others already mentionned it, you should start using
a recent compiler.

Cheers,
--
IR
Jan 10 '07 #23

P: n/a

Simon G Best wrote:
Hello!

Zorro wrote:
The simplicity of stack unraveling of C++ is not without defective
consequences. The following article points to C++ examples showing the
defects. An engineer aware of defects can avoid hard-to-find bugs.

http://distributed-software.blogspot...defective.html

I've read this thread, as well as your blog article and referenced
document (which seems to be plugging your Z++), and it seems you're
misunderstanding /why/ the behaviour of division by zero is undefined.

My guess is that the rationale behind it being undefined is something
like the following.

When a processor encounters division by zero, it may well throw an
exception (*not* a C++ exception), complain in some other way, ignore
it, or do something else. What it does depends on the processor. But,
whatever it is, it's beyond the scope of the C++ standard, because the
C++ standard is not there to define such processor behaviour.

If a processor somehow reports division by zero to, say, an operating
system, then that operating system may well respond by sending a signal
to the relevant program, terminating execution of that program, ignoring
it, or doing something else. What it does depends on the operating
system. But, whatever it is, it's beyond the scope of the C++ standard,
because the C++ standard is not there to define such operating system
behaviour.

If the C++ standard was to specify behaviour for division by zero, then
since the processor's behaviour and operating system's behaviour are
beyond the scope of the C++ standard, such specified behaviour may well
have to be implemented in such a way as to prevent the division by zero
from actually occurring in the first place. That would impose often
unnecessary and unwanted overheads. C++ just isn't that sort of language.

Indeed, there are a great many unsafe things that C++ allows programmers
to do. There are unsafe things that C++ allows programmers to do
without even throwing C++ exceptions when they're done. Instead, C++
provides mechanisms for use /when the programmer wants or needs them./
It's the programmer's responsibility to write safe code, /not/ C++
itself. So, C++ provides exception mechanisms /without/ imposing them
on the programmer. If the programmer needs well-behaved exception
handling, the programmer can then use the exception mechanisms provided
accordingly. That's the kind of language that C++ is.

So, if, when doing a division, there's the real (though hopefully
exceptional) possibility of it being a division by zero, the thing to do
is to do that division within a try block, checking for division by zero
before doing the division, and throwing an exception if it would be
division by zero. This could, of course, be wrapped up in your own
number class. No need to change the language itself.

:-)

--
Simon G Best
What happens if I mention Leader Kibo in my .signature?
There are a number of great comments, but this one sums it up rather
thoroughly.

What seems to be happening is this. When you use "throw", the compiler
generates code to destroy objects in relevant scopes, should an
exception happen. Otherwise, the compiler has no clue where to put such
code. Thus, even though exceptions (such as div by zero) are caught,
the code to call destructors (at end of try, or function body) is
simply skipped.

What that all means, again is this. There is code to destroy objects in
nested scopes. However, unless the "throw" is used, the compiler will
be caught unguarded, and code for destroying objects will be skipped.

That is fair as a standard. The compiler is just doing what the
standard requires, even VC++ 6 does it right. It is also fair to expect
the engineer to check for every possible case of exception and put a
"throw" for it.

I have no further argument on this issue. Just a comment, and nothing
else.

Given that all operating systems report errors (exceptions) rather than
crashing, and in fact the program can even check the error code, etc.
and continue to execute (perhaps taking the necessary actions), how
hard is it for the standard to have a list of common exceptions that
may happen unexpectedly?
The answer is that, the mechanism used in C++ still will need the
"throw" in order to generate code for NOT skipping the destruction of
objects.
I hope this helps, but it is not intended to start another wave. I
agree with all of you.

Thanks for your comments. Have a great day.

Regards,
zo****@ZHMicro.com
http://www.zhmicro.com
http://distributed-software.blogspot.com
http://groups-beta.google.com/group/...Z?lnk=la&hl=en

Jan 11 '07 #24

P: n/a
Zorro wrote:
Given that all operating systems report errors (exceptions) rather than
crashing, and in fact the program can even check the error code, etc.
Invalid reasoning, because the premise is false. Unless you use a definition
of "Operating system" that excludes, for example, ms-dos.

--
Salu2
Jan 11 '07 #25

P: n/a
Zorro wrote:
>
Given that all operating systems report errors (exceptions) rather than
crashing, and in fact the program can even check the error code, etc.
and continue to execute (perhaps taking the necessary actions), how
hard is it for the standard to have a list of common exceptions that
may happen unexpectedly?
Not all implementations are hosted. Even those that are (UNIX like
systems for example) may signal exception asynchronously. This makes it
extremely difficult to handle the event in the same context as the
running application in order to convert the system event into an
application one.

--
Ian Collins.
Jan 11 '07 #26

P: n/a
Zorro wrote:
>
What seems to be happening is this. When you use "throw", the compiler
generates code to destroy objects in relevant scopes, should an
exception happen. Otherwise, the compiler has no clue where to put such
code. Thus, even though exceptions (such as div by zero) are caught,
the code to call destructors (at end of try, or function body) is
simply skipped.
No. If div by zero throws an exception that's implementation-specific
behavior. If your implementation does something silly like not run
destructors as part of its implemenation-specific behavior, that's a
problem with your implementation, not with the language.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
Jan 11 '07 #27

P: n/a

Zorro wrote:
how
hard is it for the standard to have a list of common exceptions that
may happen unexpectedly?
I suspect much harder than it is for you to write

#include <eh.h>

void my_handler(UINT, struct _EXCEPTION_POINTERS* pex)
{
if(pex->ExceptionRecord->ExceptionCode ==
EXCEPTION_INT_DIVIDE_BY_ZERO)
throw divide_by_zero();
}

// main
_set_se_translator(&my_handler);

Jan 11 '07 #28

P: n/a
Zorro wrote:
how
hard is it for the standard to have a list of common exceptions that
may happen unexpectedly?
The standard has a list of all standard exceptions. Keep in mind that
hardware "exceptions" are not the same as C++ exceptions, although they
use the same name. C++ doesn't say much about hardware exceptions,
because they're too idiosyncratic. If you don't throw it, it's not
covered by the standard.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
Jan 11 '07 #29

P: n/a
Zorro wrote:
What seems to be happening is this. When you use "throw", the compiler
generates code to destroy objects in relevant scopes, should an
exception happen. Otherwise, the compiler has no clue where to put such
code. Thus, even though exceptions (such as div by zero) are caught,
the code to call destructors (at end of try, or function body) is
simply skipped.
You're wrong.
`throw' simply throws exceptions.
If you don't use `throw', no exception is thrown. `throw' is the only
way to throw exceptions in C++.
It has been told to you more than ten times already, but division by
zero does *not* throw any exception.
Given that all operating systems report errors (exceptions) rather than
crashing
Not all do, on some machines couldn't even allow it.
Jan 11 '07 #30

P: n/a
Roland Pibinger wrote:
On 9 Jan 2007 22:31:06 -0800, "Zorro" wrote:
division by 0 is undefined just as trying to deref a null
pointer. These are exceptional cases that can happen. Simply calling
them (undefined behavior) does not help in anyway.

From K&R B9:
"The header <signal.hprovides facilities for handling exceptional
conditions that arise during execution, such as an inerrupt signal
from an external source or an error in execution.
...
SIGFPE arithmetic error, e.g., zero devide or overflow
...
SIGSEGV illegal storage access, e.g., access outside memory limits"
Not particularly useful to the case in hand, as undefined
behaviour is caused if the signal handler for either of those
signals is not present, or returns (ie. to have defined behaviour
you must have a signal handler which aborts the program).

Jan 12 '07 #31

P: n/a

Ian Collins wrote:
Zorro wrote:

Given that all operating systems report errors (exceptions) rather than
crashing, and in fact the program can even check the error code, etc.
and continue to execute (perhaps taking the necessary actions), how
hard is it for the standard to have a list of common exceptions that
may happen unexpectedly?

Not all implementations are hosted. Even those that are (UNIX like
systems for example) may signal exception asynchronously. This makes it
extremely difficult to handle the event in the same context as the
running application in order to convert the system event into an
application one.

--
Ian Collins.
This is an interesting point. Indeed, there is something good in every
comment that helps design safer applications. Let me ask the question
from a different angle, though your comment does not focus on this
aspect of the question. Think of a complex program with a large number
of exceptions, and the possibility of missing something (to be done
later).

If my application did not throw an exception, and it was caused by
external events, why was it caught? I would be more than happy to see
my program crash so I could find my problem. On the other hand, if an
exceptional event can be caught by the runtime library, how come it
cannot clean up properly?

Please do not focus on div-by-zero. Think of some exceptional event,
call it unknown. So, either the catch() can trap unknown exceptions
caused by underlying system (thus, it must clean up correctly), or my
application must crash, as it would without the use of catch().

Is this a fair question?

Please, let us not blame a particular compiler implementation. This is
not specific to any compiler. Try it with your favorite compiler.

Regards,
zo****@ZHMicro.com
http://www.zhmicro.com
http://distributed-software.blogspot.com
http://groups-beta.google.com/group/...Z?lnk=la&hl=en

Jan 12 '07 #32

P: n/a
On Jan 12, 8:23 am, "Zorro" <zor...@comcast.netwrote:
Ian Collins wrote:
Zorro wrote:
Given that all operating systems report errors (exceptions) rather than
crashing, and in fact the program can even check the error code, etc.
and continue to execute (perhaps taking the necessary actions), how
hard is it for the standard to have a list of common exceptions that
may happen unexpectedly?
Not all implementations are hosted. Even those that are (UNIX like
systems for example) may signal exception asynchronously. This makes it
extremely difficult to handle the event in the same context as the
running application in order to convert the system event into an
application one.

This is an interesting point. Indeed, there is something good in every
comment that helps design safer applications. Let me ask the question
from a different angle, though your comment does not focus on this
aspect of the question. Think of a complex program with a large number
of exceptions, and the possibility of missing something (to be done
later).

If my application did not throw an exception, and it was caused by
external events, why was it caught? I would be more than happy to see
my program crash so I could find my problem. On the other hand, if an
exceptional event can be caught by the runtime library, how come it
cannot clean up properly?
Easy, it was caught because your compiler vendor decided that they
wanted it that way, as others have pointed out earlier division by 0
causes undefined behaviour, which is just that: undefined. Meaning that
just because it was caught on your system there is no guarantee that it
will on someone else system, or your system with a small upgrade, or
whatever. Once a program has entered undefined behaviour anything is
possible, it might even continue and execute the rest of the program
correctly.

--
Erik Wikström

Jan 12 '07 #33

P: n/a
Zorro wrote:
Ian Collins wrote:
>>Zorro wrote:
>>>Given that all operating systems report errors (exceptions) rather than
crashing, and in fact the program can even check the error code, etc.
and continue to execute (perhaps taking the necessary actions), how
hard is it for the standard to have a list of common exceptions that
may happen unexpectedly?

Not all implementations are hosted. Even those that are (UNIX like
systems for example) may signal exception asynchronously. This makes it
extremely difficult to handle the event in the same context as the
running application in order to convert the system event into an
application one.
Please trim signatures (your news reader should be set to do this for
you). You should also add a -- line before yours so news readers can
recognise it for what it is.
>
This is an interesting point. Indeed, there is something good in every
comment that helps design safer applications. Let me ask the question
from a different angle, though your comment does not focus on this
aspect of the question. Think of a complex program with a large number
of exceptions, and the possibility of missing something (to be done
later).

If my application did not throw an exception, and it was caused by
external events, why was it caught? I would be more than happy to see
my program crash so I could find my problem. On the other hand, if an
exceptional event can be caught by the runtime library, how come it
cannot clean up properly?
I think that is where you make your mistake, the event need not be
caught by the runtime library. It is more likely to be caught by the
operating system (if the environment is hosted) as a result of a trap
generated by the underlying hardware. The means of delivery is
dependant on the operating environment, not the running application
(which includes the C++ runtime).

The rules relating to the handling of these events are laid down by the
operating environment, not the C++ runtime. There may be some event
that can be handled by the runtime, but it is beyond the scope of the
C++ standard to mandate how these are handled for all environments.

As I said before, in a UNIX like environment, hardware exceptions are
handled through a form of software interrupt known as a signal. The
signal is processed in a different context from the application and
there isn't a means of communicating between the signal handler and the
application context. The same would apply to any system using
interrupts to handle exceptions raised by the processor.

--
Ian Collins.
Jan 12 '07 #34

P: n/a
Zorro wrote:
>
Please, let us not blame a particular compiler implementation. This is
not specific to any compiler. Try it with your favorite compiler.
On the contrary: catching exceptions that were not thrown is not part of
standard C++. If your implementation does this, you need to ask your
compiler vendor for details and, perhaps, for an explanation of how to
use it.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
Jan 12 '07 #35

P: n/a

Pete Becker wrote:
Zorro wrote:

Please, let us not blame a particular compiler implementation. This is
not specific to any compiler. Try it with your favorite compiler.

On the contrary: catching exceptions that were not thrown is not part of
standard C++. If your implementation does this, you need to ask your
compiler vendor for details and, perhaps, for an explanation of how to
use it.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
OK. This is a direct answer, and I appreciate it. Let us be more
specific.

"Catching exceptions that were not thrown is not part of standard C++".

Does this mean:

1. Exception must not be caught (generally, the program will crash).
2. Whether or not catch it is vendor-specific (outside of standard,
hence arbitrary).
3. Program becomes undefined with unpredictable behavior (hardly
useful).

Regards,
zo****@ZHMicro.com
http://www.zhmicro.com
http://distributed-software.blogspot.com
http://groups-beta.google.com/group/...Z?lnk=la&hl=en

Jan 12 '07 #36

P: n/a
On 2007-01-12 17:21, Zorro wrote:
Pete Becker wrote:
>Zorro wrote:
>
Please, let us not blame a particular compiler implementation. This is
not specific to any compiler. Try it with your favorite compiler.

On the contrary: catching exceptions that were not thrown is not part of
standard C++. If your implementation does this, you need to ask your
compiler vendor for details and, perhaps, for an explanation of how to
use it.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)

OK. This is a direct answer, and I appreciate it. Let us be more
specific.

"Catching exceptions that were not thrown is not part of standard C++".

Does this mean:

1. Exception must not be caught (generally, the program will crash).
2. Whether or not catch it is vendor-specific (outside of standard,
hence arbitrary).
3. Program becomes undefined with unpredictable behavior (hardly
useful).
It means that if you have code with a catch-block that gets executed
even though no exception has been thrown it is not standard compliant
behaviour, I would even go as far as saying that it is in direct
violation of the standard.

Just to be clear, that is not what is happening in your code, what
happens there is that you get undefined behavior. And when you get UB
anything is fair, so executing the catch-block is not exactly wrong.

--
Erik Wikström
Jan 12 '07 #37

P: n/a
Zorro wrote:
Pete Becker wrote:
>Zorro wrote:
>>Please, let us not blame a particular compiler implementation. This is
not specific to any compiler. Try it with your favorite compiler.
On the contrary: catching exceptions that were not thrown is not part of
standard C++. If your implementation does this, you need to ask your
compiler vendor for details and, perhaps, for an explanation of how to
use it.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)

OK. This is a direct answer, and I appreciate it. Let us be more
specific.

"Catching exceptions that were not thrown is not part of standard C++".

Does this mean:

1. Exception must not be caught (generally, the program will crash).
2. Whether or not catch it is vendor-specific (outside of standard,
hence arbitrary).
3. Program becomes undefined with unpredictable behavior (hardly
useful).
It means that the standard does not address it. Again: if your
implementation does this, you need to ask your compiler vendor for
details and, perhaps, for an explanation of how to use it.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
Jan 12 '07 #38

P: n/a
Erik Wikström wrote:
>
It means that if you have code with a catch-block that gets executed
even though no exception has been thrown it is not standard compliant
behaviour, I would even go as far as saying that it is in direct
violation of the standard.

Just to be clear, that is not what is happening in your code, what
happens there is that you get undefined behavior. And when you get UB
anything is fair, so executing the catch-block is not exactly wrong.
If a program has undefined behavior under the standard, the standard
does not impose any requirements. In particular, the compiler is free to
generate code that executes catch clauses even when there is no
corresponding throw.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
Jan 12 '07 #39

P: n/a
Zorro wrote:
Pete Becker wrote:
>>>
On the contrary: catching exceptions that were not thrown is not part of
standard C++. If your implementation does this, you need to ask your
compiler vendor for details and, perhaps, for an explanation of how to
use it.

OK. This is a direct answer, and I appreciate it. Let us be more
specific.

"Catching exceptions that were not thrown is not part of standard C++".

Does this mean:

1. Exception must not be caught (generally, the program will crash).
No. An exception that isn't thrown doesn't even exist. For an
exception to exist, it must be thrown. The throwing of an exception is
the creation of that exception.

Again, things that may be regarded as exceptions /outside/ of C++ /are
not/ C++ exceptions. A processor exception /is not an exception in
C++./ An exception thrown by an operating system /is not an exception
in C++./ The /only/ exceptions in C++ are exceptions thrown /within/ C++.

So, in a sense, yes: 'exceptions' that are not thrown /within/ C++
should not be caught /within/ C++. Except, of course, when it's a case
of undefined behaviour (such as with division by zero), in which case
anything's allowed to happen (including catching exceptions that weren't
thrown). That's what "undefined" means.

--
Simon G Best
What happens if I mention Leader Kibo in my .signature?
Jan 12 '07 #40

P: n/a
Zorro <zo****@comcast.netwrote:
The simplicity of stack unraveling of C++ is not without defective
consequences. The following article points to C++ examples showing the
defects. An engineer aware of defects can avoid hard-to-find bugs.

http://distributed-software.blogspot...defective.html
It seems you have confused C++ exceptions with "structured exception
handling" (SEH). SEH is provided as a Microsoft extension (you said you
were using VC++ 6.0), and Microsoft specifically says that SEH is not
specifically designed for, nor is it recommended, for C++, and that
regular C++ exception handling should be used in a C++ program.

If you use SEH, you must instead use the non-standard __try/__finally
construct.

See the following links for more information. Incidentally, one of the
examples demonstrates it with a divide-by-zero error:

http://msdn.microsoft.com/library/de...ifferences.asp

http://msdn.microsoft.com/library/de...ith_c.2b2b.asp

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Jan 12 '07 #41

P: n/a
Zorro wrote:
Pete Becker wrote:
>>Zorro wrote:
>>>Please, let us not blame a particular compiler implementation. This is
not specific to any compiler. Try it with your favorite compiler.

On the contrary: catching exceptions that were not thrown is not part of
standard C++. If your implementation does this, you need to ask your
compiler vendor for details and, perhaps, for an explanation of how to
use it.

OK. This is a direct answer, and I appreciate it. Let us be more
specific.
Please follow the advice I posted on quoting and using signatures, it
will make your posts easier to follow.
"Catching exceptions that were not thrown is not part of standard C++".
Such a beast does not exist. Something that isn't created with a throw
simply isn't an exception!

--
Ian Collins.
Jan 12 '07 #42

P: n/a

Marcus Kwok wrote:
Zorro <zo****@comcast.netwrote:
The simplicity of stack unraveling of C++ is not without defective
consequences. The following article points to C++ examples showing the
defects. An engineer aware of defects can avoid hard-to-find bugs.

http://distributed-software.blogspot...defective.html

It seems you have confused C++ exceptions with "structured exception
handling" (SEH). SEH is provided as a Microsoft extension (you said you
were using VC++ 6.0), and Microsoft specifically says that SEH is not
specifically designed for, nor is it recommended, for C++, and that
regular C++ exception handling should be used in a C++ program.

If you use SEH, you must instead use the non-standard __try/__finally
construct.

See the following links for more information. Incidentally, one of the
examples demonstrates it with a divide-by-zero error:

http://msdn.microsoft.com/library/de...ifferences.asp

http://msdn.microsoft.com/library/de...ith_c.2b2b.asp

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Thanks for the links Marcus. They make it clear that, if you do use
throw the destructors will be called with much less overhead. But if
you miss on some possible exception that may occur, then the jump to
the catch section will occur but the clean up may not be done as needed
(In MS context). Thus, it is the engineer that must remember every
little detail.

I was not talking about how to catch other kinds of exceptions (given
that I remember them in a complex program), but the comments went in
that direction. Also, I am saying this behavior is not unique to VC++.
If that were the case, this would end the discussion.

Whether or not a raised exception is "thrown", the control from the try
block makes a jump to the catch() section. That is what I meant by
"catching none-thrown exceptions".

Thanks again.

Regards,
zo****@ZHMicro.com
http://www.zhmicro.com
http://distributed-software.blogspot.com
http://groups-beta.google.com/group/...Z?lnk=la&hl=en

Jan 12 '07 #43

P: n/a

Simon G Best wrote:
Zorro wrote:
Pete Becker wrote:
>>
On the contrary: catching exceptions that were not thrown is not part of
standard C++. If your implementation does this, you need to ask your
compiler vendor for details and, perhaps, for an explanation of how to
use it.
OK. This is a direct answer, and I appreciate it. Let us be more
specific.

"Catching exceptions that were not thrown is not part of standard C++".

Does this mean:

1. Exception must not be caught (generally, the program will crash).

No. An exception that isn't thrown doesn't even exist. For an
exception to exist, it must be thrown. The throwing of an exception is
the creation of that exception.

Again, things that may be regarded as exceptions /outside/ of C++ /are
not/ C++ exceptions. A processor exception /is not an exception in
C++./ An exception thrown by an operating system /is not an exception
in C++./ The /only/ exceptions in C++ are exceptions thrown /within/ C++.

So, in a sense, yes: 'exceptions' that are not thrown /within/ C++
should not be caught /within/ C++. Except, of course, when it's a case
of undefined behaviour (such as with division by zero), in which case
anything's allowed to happen (including catching exceptions that weren't
thrown). That's what "undefined" means.

--
Simon G Best
What happens if I mention Leader Kibo in my .signature?
I will try to bring together your comments as a reply to Simon. My
apologies should I misinterpret your comments.

Replying to Simon.

You are very specific about not catching exceptions that were not
thrown within a program, because they do not even exist. This settles
the main aspect of the issue, assuming that is how the standard
stipulates this matter.
Then, you add, other events such as "file not found", "read
error" and "div by 0" put the program in an undefined state in
which it may behave in an undefined manner. I am asking if the standard
uses the term "undefined" in this context. Here is what Pete says.

"It means that the standard does not address it. Again: if your
implementation does this, you need to ask your compiler vendor for
details and, perhaps, for an explanation of how to use it".

So, does "undefined" mean that the standard does not address it, or
does it mean that the standard specifically mentions, "undefined
behavior"?

Erik says "It means that if you have code with a catch-block that
gets executed even though no exception has been thrown it is not
standard compliant behavior, I would even go as far as saying that it
is in direct violation of the standard".

A very specific and clear statement. But again, Erik immediately brings
up undefined behavior.

Is "undefined behavior", in this context, mentioned in the
standard? It will be nice someone familiar with standard to kindly
tells us where this is stated.

My opinion is what it was some 20 years ago with regard to the
implementation in the experimental compiler.

"If your design requires the use of throw in order to behave
logically, then it must remain oblivious with regard to an exception
not raised by a throw".

Please note that what this means is the following "For any exception
not thrown in a try block, the control must not jump to the catch
section".

Finally, considering the difficulty of implementation, it is fine to
make the jump (i.e. catch any exception as it comes), without having a
corresponding name for it. Just label them as "Unknown Exception",
but do the clean up so the program does not behave unpredictably.

The best way to resolve this is an answer like this. Standard item
number such and such states that .... Or, standard does not address
this issue for now.

Please note the following, which seems to get lost in your replies.

"When the majority (if not all) compilers do the same thing, one
takes the behavior for granted very much like an implicit standard.
Specifically, for exceptions not thrown by an application, they make
the jump to the catch section (the exceptions are caught anyway)".

You are addressing this issue by pointing to a particular example that
I have presented as "undefined". So, are you saying any none-thrown
exception is "undefined"? If not, can you give an example (and your
choice of compiler) that "does not catch a none-thrown exception"?

Regards,
zo****@ZHMicro.com
http://www.zhmicro.com
http://distributed-software.blogspot.com
http://groups-beta.google.com/group/...Z?lnk=la&hl=en

Jan 12 '07 #44

P: n/a
Zorro wrote:
>
Whether or not a raised exception is "thrown", the control from the try
block makes a jump to the catch() section. That is what I meant by
"catching none-thrown exceptions".
Exceptions are raised *by throwing them.* In C++, that's what raising
an exception is. You can't have a raised exception that isn't thrown,
because you can't have a /thrown/ exception that isn't thrown.

--
Simon G Best
What happens if I mention Leader Kibo in my .signature?
Jan 12 '07 #45

P: n/a
Zorro wrote:

*PLEASE* follow my advice on regarding signatures!
>
Please note the following, which seems to get lost in your replies.

"When the majority (if not all) compilers do the same thing, one
takes the behavior for granted very much like an implicit standard.
Specifically, for exceptions not thrown by an application, they make
the jump to the catch section (the exceptions are caught anyway)".
The only platform I know that does this in windows, so there isn't any
de facto standard here.
You are addressing this issue by pointing to a particular example that
I have presented as "undefined". So, are you saying any none-thrown
exception is "undefined"? If not, can you give an example (and your
choice of compiler) that "does not catch a none-thrown exception"?
It's beyond undefined, it's outside of the scope of the C++ standard and
squarely in the scope of the operating environment.

If the operating environment chooses to abort an application in the
event of a asynchronous event, there is nothing the C++ compiler can do
to circumvent this behaviour.

--
Ian Collins.
Jan 12 '07 #46

P: n/a

Zorro wrote:
Simon G Best wrote:
Zorro wrote:
Pete Becker wrote:
>>>
>On the contrary: catching exceptions that were not thrown is not part of
>standard C++. If your implementation does this, you need to ask your
>compiler vendor for details and, perhaps, for an explanation of how to
>use it.
>
OK. This is a direct answer, and I appreciate it. Let us be more
specific.
>
"Catching exceptions that were not thrown is not part of standard C++".
>
Does this mean:
>
1. Exception must not be caught (generally, the program will crash).
No. An exception that isn't thrown doesn't even exist. For an
exception to exist, it must be thrown. The throwing of an exception is
the creation of that exception.

Again, things that may be regarded as exceptions /outside/ of C++ /are
not/ C++ exceptions. A processor exception /is not an exception in
C++./ An exception thrown by an operating system /is not an exception
in C++./ The /only/ exceptions in C++ are exceptions thrown /within/ C++.

So, in a sense, yes: 'exceptions' that are not thrown /within/ C++
should not be caught /within/ C++. Except, of course, when it's a case
of undefined behaviour (such as with division by zero), in which case
anything's allowed to happen (including catching exceptions that weren't
thrown). That's what "undefined" means.

--
Simon G Best
What happens if I mention Leader Kibo in my .signature?

I will try to bring together your comments as a reply to Simon. My
apologies should I misinterpret your comments.

Replying to Simon.

You are very specific about not catching exceptions that were not
thrown within a program, because they do not even exist. This settles
the main aspect of the issue, assuming that is how the standard
stipulates this matter.
Then, you add, other events such as "file not found", "read
error" and "div by 0" put the program in an undefined state in
which it may behave in an undefined manner. I am asking if the standard
uses the term "undefined" in this context. Here is what Pete says.

"It means that the standard does not address it. Again: if your
implementation does this, you need to ask your compiler vendor for
details and, perhaps, for an explanation of how to use it".

So, does "undefined" mean that the standard does not address it, or
does it mean that the standard specifically mentions, "undefined
behavior"?

Erik says "It means that if you have code with a catch-block that
gets executed even though no exception has been thrown it is not
standard compliant behavior, I would even go as far as saying that it
is in direct violation of the standard".

A very specific and clear statement. But again, Erik immediately brings
up undefined behavior.

Is "undefined behavior", in this context, mentioned in the
standard? It will be nice someone familiar with standard to kindly
tells us where this is stated.

My opinion is what it was some 20 years ago with regard to the
implementation in the experimental compiler.

"If your design requires the use of throw in order to behave
logically, then it must remain oblivious with regard to an exception
not raised by a throw".

Please note that what this means is the following "For any exception
not thrown in a try block, the control must not jump to the catch
section".

Finally, considering the difficulty of implementation, it is fine to
make the jump (i.e. catch any exception as it comes), without having a
corresponding name for it. Just label them as "Unknown Exception",
but do the clean up so the program does not behave unpredictably.

The best way to resolve this is an answer like this. Standard item
number such and such states that .... Or, standard does not address
this issue for now.

Please note the following, which seems to get lost in your replies.

"When the majority (if not all) compilers do the same thing, one
takes the behavior for granted very much like an implicit standard.
Specifically, for exceptions not thrown by an application, they make
the jump to the catch section (the exceptions are caught anyway)".

You are addressing this issue by pointing to a particular example that
I have presented as "undefined". So, are you saying any none-thrown
exception is "undefined"? If not, can you give an example (and your
choice of compiler) that "does not catch a none-thrown exception"?

Regards,
zo****@ZHMicro.com
http://www.zhmicro.com
http://distributed-software.blogspot.com
http://groups-beta.google.com/group/...Z?lnk=la&hl=en
In response to several comments after this posting:

Let us be fair. Do not reply to a paragraph, somewhat out ot context. I
am asking a couple of specific questions. If someone is familiar with
the standard, please point out where should we look in the standard.
Please, kindly show an example, and your choice of compiler, as I have
requested. Some of the comments simply say "Only MS VC++ does that".
Well, can you create an example using another compiler that does not?
Playing with words can go on forever, such as "An exception that is not
thrown is not an exception".
Please show an example that does not do what I am saying is happening.
Do not simply say that it is not happening. Show us how it is not
happening.

Please read the whole comment and kindly provide an answer to the
questions asked, not to individual phrases.

Thank you very much for all your input, so far.

Regards.

Jan 12 '07 #47

P: n/a
On 2007-01-12 22:24, Zorro wrote:
Simon G Best wrote:

Erik says "It means that if you have code with a catch-block that
gets executed even though no exception has been thrown it is not
standard compliant behavior, I would even go as far as saying that it
is in direct violation of the standard".

A very specific and clear statement. But again, Erik immediately brings
up undefined behavior.
Sorry if that was unclear, what I meant to say was that while I can't
cite any specific part of the standard I'm quite sure that it specifies
that all exceptions have to be throw. As no such things happens in your
example I claim that there is no exception.
Is "undefined behavior", in this context, mentioned in the
standard? It will be nice someone familiar with standard to kindly
tells us where this is stated.
[snip]
The best way to resolve this is an answer like this. Standard item
number such and such states that .... Or, standard does not address
this issue for now.
I don't own a copy of the standard but I've got a copy of a draft for
the next standard, which I hope will suffice.

1.3.13 undefined behavior [defns.undefined]

behavior, such as might arise upon use of an erroneous program construct
or erroneous data, for which this International Standard mposes no
requirements. Undefined behavior may also be expected when this
International Standard omits the description of any explicit definition
of behavior. [ Note: permissible undefined behavior ranges from ignoring
the situation completely with unpredictable results, to behaving during
translation or program execution in a documented manner characteristic
of the environment (with or without the issuance of a diagnostic
message), to terminating a translation or execution (with the issuance
of a diagnostic message). Many erroneous program constructs do not
engender undefined behavior; they are required to be diagnosed. —end note ]

The following might also be of interest:

5.6 Multiplicative operators [expr.mul]

4th paragraph

The binary / operator yields the quotient, and the binary % operator
yields the remainder from the division of the first expression by the
second. If the second operand of / or % is zero the behavior is
undefined; otherwise (a/b)*b + a%b is equal to a. If both operands are
nonnegative then the remainder is nonnegative; if not, the sign of the
remainder is implementation-defined).

Hope that helps.

--
Erik Wikström
Jan 12 '07 #48

P: n/a
Zorro wrote:
>
In response to several comments after this posting:

Let us be fair. Do not reply to a paragraph, somewhat out ot context. I
am asking a couple of specific questions. If someone is familiar with
the standard, please point out where should we look in the standard.
This is out of the scope of the standard!
Please, kindly show an example, and your choice of compiler, as I have
requested. Some of the comments simply say "Only MS VC++ does that".
Well, can you create an example using another compiler that does not?
Playing with words can go on forever, such as "An exception that is not
thrown is not an exception".
Please show an example that does not do what I am saying is happening.
Do not simply say that it is not happening. Show us how it is not
happening.
This is becoming tedious.

Your own example:

#include <iostream>

struct simple
{
int s;
simple() { s = 5;}
~simple(void) {std::cout << "Destructor ..." << std::endl;}
};

int main(){
int i = 1, j = 0;
try {
simple spl;
int k = i/j;
}
catch(...) {
std::cout << "Caught it" << std::endl;
}
std::cout << "Finishing" << std::endl;
return 0;
}

compiled with gcc on Solaris or Linux aborts.

../a.out
Arithmetic Exception (core dumped)

--
Ian Collins.
Jan 12 '07 #49

P: n/a
Just to clarify...

Ian Collins wrote:
>
./a.out
Arithmetic Exception (core dumped)
That "Arithmetic Exception", I bet, is *not* a C++ exception, but some
other kind of exception beyond C++. (Just thought I'd better clarify
that, just in case Zorro mistakes it for a C++ exception.)

--
Simon G Best
What happens if I mention Leader Kibo in my .signature?
Jan 12 '07 #50

132 Replies

This discussion thread is closed

Replies have been disabled for this discussion.