Look at this :
http://www.a1one.com/onlinebooks/Cplus/
or
http://documentation.captis.com/files/c++/handbook/
CHAPTER 6 - EXCEPTION HANDLING
Serge.
There are times when you don't know what to do in one of the two parts
of the if-else. For example std::vector::at. What should the library
vendor do if the input value is out of range? In some programs it would
be approprate to quit, in some it would be approprate to add to the
vector until the value is in range, in some it would be approprate to
ask the user what to do... The library vendor can't know what to do in
this situation so he throws an exception.
There are times when you don't have the data available at the location
in the code where the if-else should go. For example even if the person
implementing vector::at knew that he should ask the user what to do, he
doesn't have access to the windowing code to ask the question with.
The reasons won't be obvious to you until you acquire more maturity in
the sphere of computing. The first programming languages did not have
exception handling either: it took many years to invent that idea.
One explanation is this: the place in the program where some condition
occurs is not always the best place for the responsibility handling
that condition.
There are analogies in real life. If you buy some appliance and it
breaks, do you fix it yourself? No; you have the responsibility of
using the device in the normal way to do some task. If it breaks, you
pass the responsibility to the vendor, who can go to the manufacturer,
who is respnosible for defects in the device under warranty. You can't
be an expert at everything! You may be a wicked chef, but have no clue
how to fix a broken blender.
Exception handling is a way of automating the responsibility passing,
so you that you don't have to write an ``if-then'' for the sole
purpose of passing the responsibility to the calling code. The problem
with that approach is that then every level in the calling chain has
to handle every possible condition from below and pass it upward, or
decide to handle it.
Exception handling provides a dynamic matching system by which the
responsible module can be found and invoked directly, without the
involvement of every middle layer. It's like the broken appliance
being smart enough to call the manufacturer all by itself and get
repaired, or something like that.
Without exception handling, you code which implements the chef also
has to be an expert blender-repairer. Once you start mixing and
spreading responsibilities in this way, you risk introducing errors
and maintenance problems into the software.
> I have been trying to
> understand the reason behind using the Exception for 2 weeks without any
> success. I am learning Java now but C++ use the same concept!! thanks
The solution to your problem is to keep using exceptions for a few
years.
I've been writing code for 25 years and I still need to acquire more
maturity ... Darn it.
The true answer is "You don't NEED exceptions", however it is
*SOMETIMES* and elegant solution to a bad design.
My advice is to NOT use exceptions unless this is the only mechanism
that will solve your problem (i.e. a callback gets called and has no
other way to respond to a condition). However, allways write
exception-safe code. The tennant being, be liberal about what your code
accepts and limited about what it does. If you don't know what
exception safe code is, then ask, it's a very important concept, it
makes your code much easier (IMHO) to understand and maintain as a side
effect of also being exception safe.
G
> The true answer is "You don't NEED exceptions", however it is
> *SOMETIMES* and elegant solution to a bad design.
You don't need while nor for, you can write good-old spaghetti code ;)
Regards.
It doesn't answer the question.
> There are times when you don't know what to do in one of the two parts
> of the if-else. For example std::vector::at. What should the library
> vendor do if the input value is out of range? In some programs it would
> be approprate to quit, in some it would be approprate to add to the
> vector until the value is in range, in some it would be approprate to
> ask the user what to do... The library vendor can't know what to do in
> this situation so he throws an exception.
>
> There are times when you don't have the data available at the location
> in the code where the if-else should go. For example even if the person
> implementing vector::at knew that he should ask the user what to do, he
> doesn't have access to the windowing code to ask the question with.
This doesn't explain why you would "throw" an exception object
instead of simply returning an exception object.
> The reasons won't be obvious to you until you acquire more maturity in
> the sphere of computing.
Once you acquire more maturity,
you will realize that you don't know all the answers
and you will refrain from attempting to answer questions
when you don't know the answer -- well, we can hope ;-)
It does when you realise the return value of at is of type
reference-to-element.
Jon.
Elaborate a little please.
Tell us why
std::vector::at(exception& e, int i)
wasn't provided by the standard library?
Probably because there was no demand for such idiotic thing(s).
regards,
alexander.
What languages have you used that have exception handling systems?
If your experience with EH has been largely through C++ or similar, I
could understand where you are coming from. Exception handling in C++
is awkward and crude, for these reasons:
- The search for a matching handler unwinds as it searches, making it
impossible to restart the program at some point nested in between the
originating point of the exception and the handler.
- Awkward static declarations which limit what may be thrown out of
some function, which render the code useless as a shim between
arbitrary components that could throw anything to each other.
- No ``finally'' blocks for doing simple clean-up actions that take
place regardless of how a block of code terminates.
- No decent macro system to implement simpler constructs that reduce
to machine-generated try-catch.
> The true answer is "You don't NEED exceptions", however it is
> *SOMETIMES* and elegant solution to a bad design.
Need is a very bad criterion, because a human being can get by on very
little. Strictly speaking, you don't need running water or
electricity, or shoes, etc.
> My advice is to NOT use exceptions unless this is the only mechanism
> that will solve your problem (i.e. a callback gets called and has no
My meta-advice is not to use C++ unless it's the only mechanism that
will solve your problem. :)
Because you would have to write such idiotic code as this:
int foo(exception& e)
{
vector<int> v;
exception ex;
int value = v.at(ex, 9);
if(ex.raised())
{
e = ex;
return MAGIC_VALUE;
}
else
return value;
}
In this contrived example, there is more code concerning exception
propagation than there is concerning functionality, and you would have to do
something similar in each and every function that is to pass exceptions up
the call stack. Note also that you have to invade the parameter-list of each
function too. And it could get worse. What if you want to handle different
types of exceptions? How do you even "throw" an exception derived from the
base exception class? Maybe you could change to pass by pointer, and create
the exception using "new", and then have NULL as the "not raised" indicator
(don't forget the clean-up logic). But then, how do you throw something that
isn't derived from the base exception class?
Perhaps you want to catch one type of exception and propagate another, which
means the if statement gets bigger and harder to maintain. What if you have
a function which can't propagate exceptions and you need to change it so
that it can? You need to change the interface of the function, and you need
to add all the propagation logic. Ultimately, you'd end up hard-coding all
the possible propagation paths and logic into the program which would
require a lot of code and hugely increase the probability of introducing
bugs.
Jon.
I see that you haven't been threatening to contact people's employers
lately, and that you have long discontinued your blacklist webpage.
These too are welcome signs of improved maturity. Or at least of an
improved adherence to a more successful social strategy.
Why don't you troll somewhere else?
*PLONK*
> the call stack. Note also that you must invade the parameter-list of each
> function too. And it could get worse. What if you want to handle different
> types of exceptions? How do you even "throw" an exception derived from the
> base exception class? Maybe you could change to pass by pointer, and create
> the exception using "new", and then have NULL as the "not raised" indicator
> (don't forget the clean-up logic). But then, how do you throw something that
> isn't derived from the base exception class?
>
> Perhaps you want to catch one type of exception and propagate another, which
> means the if statement gets bigger and harder to maintain. What if you have
> a function which can't propagate exceptions and you need to change it so
> that it can? You need to change the interface of the function, and you need
> to add all the propagation logic. Ultimately, you'd end up hard-coding all
> the possible propagation paths and logic into the program
> which would require a lot of code
> and hugely increase the probability of introducing bugs.
Your example and explanation are a bit disappointing.
It isn't clear from your example
whether the logic in function foo(exception&)
actually handles the exception or not.
I will assume that it does not handle the exception at all
but you were still left with the problem of returning a value
so that foo(exception&) could be used in an expression.
This is the same problem that the standard library designers faced
in returning a value from std::vector::at(int)
but you failed to address that problem in your example.
You could have written:
int foo(exception& e) {
vector<int> v;
exception ex;
int value = v.at(ex, 9);
e = ex;
return value;
}
Suppose instead that you had written:
int foo(void) {
vector<int> v;
int value = 0;
try {
value = c.at(9);
}
catch (std::out_of_range e) {
throw other_exception_type(e);
}
return value;
}
This is at least as messy as any code that
you might have written to return an exception
instead of throwing an exception.
Your argument about the [automatic] propagation
of exceptions is weak because exceptions are usually caught
close to the point where they occur or they are not caught at all.
There is no point in throwing an exception
unless you expect it to be caught and handled at some point.
Otherwise, you might as well abort the program
at the point where the exception occurs
because the the program is going to abort anyway
unless the exception is handled.
The only substantial advantage of throwing an exception
over returning an exception when a function returns by value
is that you can use that function in an expression
embedded in a try block.
If the function throws an exception,
evaluation of the expression is aborted and
control is transfer to the appropriate catch block
where the exception can be handled.
> There is no point in throwing an exception
> unless you expect it to be caught and handled at some point.
> Otherwise, you might as well abort the program
> at the point where the exception occurs
> because the the program is going to abort anyway
> unless the exception is handled.
You simply throw the exception, and the user of the function (or the
function that calls that function or...) catches it if want to do that
or let the program abort if not. The function needs not to take the
decision of if the program as a whole can manage the situation or not.
Regerds.
> You simply throw the exception and the users of the function
> (or the function that calls that function or...) catch it
> if they want to do that or let the program abort if not.
> The function needs not to take the decision
> whether the program as a whole can manage the situation or not.
No.
Good programmers never "simply" throw an exception.
A good programmer must show that the exception
can be caught and handled -- at least partially.
I suspect that you are an exception abuser.
You probably throw exceptions
even when they can be handled within the scope
of the function where they are discovered
and your exception objects probably include
insufficient information to handle the exception
in the calling function.
Lazy programmers use exceptions to convert their problems
into someone else's problems without consideration
for whether the exception can be caught and handled
successfully.
I think that answer is simple.
[1] It is a hard work to check every returning value (assuming that
return value = error code) from any function that can POTENTIALLY fail
to do its job.
[2] Actually, every programmer doesn't check all return codes that
must be checked. They (me too) think like this "this function never
fails". So error handing is incomplete by definition.
[3] Why should I check error condition if I am sure, that this
function ALMOST NEVER fails? I know it can - but only sometimes. Only
in case of some EXCEPTION. My local error-handling code will ALMOST
NEVER be executed. But size of program will be increased - performance
issue.
[4] Calling code may not have enough information to correctly process
error condition - in usual (with fully-implemented error handling
strategy :) ) program error will be reported to higher levels. Careful
programming required!
[5] Why should I repeat almost equivalent error checking code in every
function, which will propagate errors to higher levels of the program.
To level having enough information to deal with such error. It is
error-prone solution - Ctrl-C/Ctrl-V "technique" may be involved. I
think that macros will be used - bad.
I think that these points assure you, that exceptions are good things.
But exeptions are not free of charge. Performance of exception
mechanism is relativly poor - so exceptions must be used only in case
of exceptional conditions, but not in case of normal program flow.
Example (installation prg): function CheckFreeSpaceOnDisk(const int
nDevNum)
[a] bad desing
void CheckFreeSpaceOnDisk(const int nDevNum) throw
(FreeSpaceException)
[b] good one
bool CheckFreeSpaceOnDisk(const int nDevNum) //function may throw
exceptions
We must not use exceptions to indicate NORMAL condition - not enough
space on device. It is not exeptional condition.
But we can use exception to indicate that nDevNum is not referencing
correct device (out of range). This exeption probably will be passed
to high program level - user interaction level, skipping all
intermediate code levels (functions: UnPackAndWriteFileGroup,
DoInstall). Only GUI function OnGuiDoInstall will catch exception
onbject and report error to user. And one more point
[6] Exception is an object (as usual). You can pass to cather not only
error code (in this case information about error origin, error
description is lost), but compound data structure, which fully
describes the problem. Keep in mind that only low level has full
information about error itself, but only high level knows what to do
with it. More detailed error description is better than just one error
code!
Kirill
>>> Tell us why
>>>
>>> std::vector::at(exception& e, int i)
>>>
>>> wasn't provided by the standard library?
>>
>>
>> Because you would have to write such idiotic code as this:
>>
>> int foo(exception& e) {
>> vector<int> v;
>> exception ex;
>> int value = v.at(ex, 9);
>> if(ex.raised()) {
>> e = ex;
>> return MAGIC_VALUE;
>> }
>> else
>> return value;
>> }
[..]
> Your example and explanation are a bit disappointing.
Sorry to disappoint you.
> It isn't clear from your example
> whether the logic in function foo(exception&)
> actually handles the exception or not.
Then that's another drawback of the approach.
> I will assume that it does not handle the exception at all
> but you were still left with the problem of returning a value
> so that foo(exception&) could be used in an expression.
> This is the same problem that the standard library designers faced
> in returning a value from std::vector::at(int)
> but you failed to address that problem in your example.
> You could have written:
>
> int foo(exception& e) {
> vector<int> v;
> exception ex;
> int value = v.at(ex, 9);
> e = ex;
> return value;
> }
OK. Assume that, in my earlier code, the else clause does something with the
return value of at before returning. Then you have to check whether the
exception has been raised before deciding to take the else branch. You don't
continue processing if an exception is thrown.
> Suppose instead that you had written:
>
> int foo(void) {
> vector<int> v;
> int value = 0;
> try {
> value = c.at(9);
> }
> catch (std::out_of_range e) {
> throw other_exception_type(e);
> }
> return value;
> }
>
> This is at least as messy as any code that
> you might have written to return an exception
> instead of throwing an exception.
Yes, but it's not the same. My example is simply propagating the exception,
and not handling it.
> Your argument about the [automatic] propagation
> of exceptions is weak because exceptions are usually caught
> close to the point where they occur or they are not caught at all.
What do you base that claim on? I have plenty of code which throws
exceptions through several layers before they are handled, and I think it
works reasonably well. It's actually quite weak to claim automatic
propagation of exceptions isn't a problem based on what you assume other
people do or do not do. With your suggestion, automatic propagation becomes
a problem that makes it undesirable to propagate exceptions through several
layers, regardless of whether that is the right thing to do. The decision is
being imposed on you not to do it due to the sheer effort involved in
getting it right.
> There is no point in throwing an exception
> unless you expect it to be caught and handled at some point.
> Otherwise, you might as well abort the program
> at the point where the exception occurs
> because the the program is going to abort anyway
> unless the exception is handled.
When an unhandled exception is raised, my compiler gives the message
"abnormal program termination". I'd contend that a more informative program
termination message can sometimes be provided by installing a default
handler.
> The only substantial advantage of throwing an exception
> over returning an exception when a function returns by value
> is that you can use that function in an expression
> embedded in a try block.
That depends if I agree with your reasoning to this point. I don't. I agree
that is one advantage, but it's not the "only substantial advantage".
Jon.
> > You simply throw the exception and the users of the function
> > (or the function that calls that function or...) catch it
> > if they want to do that or let the program abort if not.
> > The function needs not to take the decision
> > whether the program as a whole can manage the situation or not.
>
> No.
> Good programmers never "simply" throw an exception.
> A good programmer must show that the exception
> can be caught and handled -- at least partially.
Yes, the programmer "simply" document that. As simply as document that a
function does not throw.
> I suspect that you are an exception abuser.
Well, you can suspect what you want, but I'm innoncent unless you prove
I'm guilty.
Regards.
> E. Robert Tisdale escribió:
>>I suspect that you are an exception abuser.
>
>
> Well, you can suspect what you want
> but I'm innocent unless you prove I'm guilty.
OK. But just remember -- We're watching you now ;-)
Take a look at the response by Soukhonossenko Kirill
and try to convince yourself that
he is not an exception abuser.
> I think that answer is simple.
[sigh . . .]
> [1] It is a hard work to check every returning value
> (assuming that return value = error code)
> from any function that can POTENTIALLY fail to do its job.
So the C++ exception handling mechanism was designed
to support lazy programmers?
> [2] Actually, every programmer doesn't check all return codes
> that must be checked. They (me too) think like this,
> "this function never fails".
> So error handing is incomplete by definition.
You don't need to check the error code if you can PROVE
that the function never fails.
> [3] Why should I check error condition
> if I am sure that this function ALMOST NEVER fails?
> I know it can - but only sometimes. Only in case of some EXCEPTION.
> My local error-handling code will ALMOST NEVER be executed.
> But size of program will be increased - performance issue.
You must ALWAYS check the "error condition" if the function can fail
AND it is possible to handle the exception satisfactorily.
> [4] Calling code may not have enough information
> to correctly process error condition - in usual
> (with fully-implemented error handling strategy :) )
> program error will be reported to higher levels.
> Careful programming required!
This makes no sense. It could apply
whether or not the C++ exception handling mechanism is used.
> [5] Why should I repeat almost equivalent error checking code in every
> function, which will propagate errors to higher levels of the program.
Why would you?
Just return the exception object to the calling function.
> To level having enough information to deal with such error.
> It is error-prone solution -
> Ctrl-C/Ctrl-V "technique" may be involved.
> I think that macros will be used - bad.
This makes no sense. An example might help.
> I think that these points assure you, that exceptions are good things.
> But exceptions are not free of charge. Performance of exception
> mechanism is relatively poor - so exceptions must be used only in case
> of exceptional conditions, but not in case of normal program flow.
>
> Example (installation prg):
> function CheckFreeSpaceOnDisk(const int nDevNum)
>
> [a] bad design
> void CheckFreeSpaceOnDisk(const int nDevNum)
> throw (FreeSpaceException)
> [b] good one
> bool CheckFreeSpaceOnDisk(const int nDevNum)
> // function may throw exceptions
What does this mean?
How do C++ application programmers know which exceptions
they should try to catch and handle?
> We must not use exceptions to indicate NORMAL condition -
> not enough space on device. It is not exceptional condition.
Why attempt to allocate space
if you don't expect that any space will be available?
Isn't that just an exercise in futility?
> But we can use exception to indicate that nDevNum is not referencing
> correct device (out of range). This exception probably will be passed
> to high program level - user interaction level, skipping all
> intermediate code levels (functions: UnPackAndWriteFileGroup,
> DoInstall). Only GUI function OnGuiDoInstall will catch exception
> object and report error to user. And one more point
>
> [6] Exception is an object (as usual). You can pass to catcher
> not only error code (in this case information about error origin,
> error description is lost), but compound data structure
> which fully describes the problem. Keep in mind that
> only low level has full information about error itself
> but only high level knows what to do with it.
> More detailed error description is better than just one error code!
This argument is invalid because you can return exception objects
instead of throwing them.
Yes. I am sure that most of us are lazy programmers. We are REAL
programmers - not IDEAL programmers. You can treat exception technique
as support system - which handle all unhandled error situation and
gives opportunity to recover (from some checkpoint) or to abort
execution. Good program must not continue its execution in undefined
state. Abort is better.
> > [2] Actually, every programmer doesn't check all return codes
> > that must be checked. They (me too) think like this,
> > "this function never fails".
> > So error handing is incomplete by definition.
>
> You don't need to check the error code if you can PROVE
> that the function never fails.
Have you seen programmer proving (in math. sense) its code? Are you
academic programmer?
>
> > [3] Why should I check error condition
> > if I am sure that this function ALMOST NEVER fails?
> > I know it can - but only sometimes. Only in case of some EXCEPTION.
> > My local error-handling code will ALMOST NEVER be executed.
> > But size of program will be increased - performance issue.
>
> You must ALWAYS check the "error condition" if the function can fail
> AND it is possible to handle the exception satisfactorily.
What do you mean by "satisfactorily"? Do you mean "pass to caller" or
show error message box?
Answer to me one simple question - do you check every function (from
OS API, C lib, etc) that returns error code? Is your code a
if-then-else mess? If not - you are REAL programmer. In case of some
unforseen situation you program will be in undefined state. Is it
exception? Yes.
> > [4] Calling code may not have enough information
> > to correctly process error condition - in usual
> > (with fully-implemented error handling strategy :) )
> > program error will be reported to higher levels.
> > Careful programming required!
>
> This makes no sense. It could apply
> whether or not the C++ exception handling mechanism is used.
I meant that you must implement error-passing mechanism by hand if you
dont use exceptions. It is error-prone approach. But you can if you
want it too much. If you think that your code will be better in this
case. Will it be faster?
> > [5] Why should I repeat almost equivalent error checking code in every
> > function, which will propagate errors to higher levels of the program.
>
> Why would you?
> Just return the exception object to the calling function.
Yes. Sure. But do you use any libraries or everytime write your code
from scratch? C++ provide you with this (error-passing) facility
implicitly. Useful programming pattern was added to language - why
write it by hand?
> > Example (installation prg):
> > function CheckFreeSpaceOnDisk(const int nDevNum)
> >
> > [a] bad design
> > void CheckFreeSpaceOnDisk(const int nDevNum)
> > throw (FreeSpaceException)
> > [b] good one
> > bool CheckFreeSpaceOnDisk(const int nDevNum)
> > // function may throw exceptions
> What does this mean?
> How do C++ application programmers know which exceptions
> they should try to catch and handle?
It is part of function interface. It must be described in doc. Do you
read program documentation, manuals, how-toos? K&R? Or you just use
functions without knowing what some function really do? I repeat -
exceptions are part of function/class interface.
> > We must not use exceptions to indicate NORMAL condition -
> > not enough space on device. It is not exceptional condition.
>
> Why attempt to allocate space
> if you don't expect that any space will be available?
> Isn't that just an exercise in futility?
I expect that space will be unavailable. It is not exception. I dont
use exception in this case. I use it in case of invalid argument.
> > [6] Exception is an object (as usual). You can pass to catcher
> > not only error code (in this case information about error origin,
> > error description is lost), but compound data structure
> > which fully describes the problem.
> This argument is invalid because you can return exception objects
> instead of throwing them.
Ok. you are right. But did you see such code? I didnt. And this point
is not most important.
I know that exceptions are slow, but they are exceptions so they
shouldnt occure often. If they occure often - they are not exceptions
- redesign you application.
If you disagree - explain & describe your approach to error-handling.
And we'll compare you approach with "exceptional" one.
May be your approach will be included in next version of C#.
[ ... ]
> The reasons won't be obvious to you until you acquire more maturity in
> the sphere of computing. The first programming languages did not have
> exception handling either: it took many years to invent that idea.
Actually, it took only a relatively short time to invent the idea, but
took quite a while for the idea to make it into a fair number of
mainstream languages.
Exception handling was included in PL/I (1963), BASIC (1964) and Algol
68 (1968, of course). The versions in PL/I and BASIC were _quite_
primitive, and Algol 68 never achieved a high level of popularity
(though it's influenced language design quite heavily since).
I'd add that quite a few people who seem to have a fairly high level of
maturity in computing see exception handling as unnecessary. Just for
example, Niklaus Wirth once commented to the effect that anybody who
thought he needed exception handling really needed to learn how to
program instead. This was shortly after quitting the Algol 68 committee
and its arguments over exception handling.
--
Later,
Jerry.
The universe is a figment of its own imagination.
[ ... ]
> So the C++ exception handling mechanism was designed
> to support lazy programmers?
Yes, but in programming (as most other things) laziness is really a
virtue. Lacking laziness, we would lack any drive to be efficient.
> > [2] Actually, every programmer doesn't check all return codes
> > that must be checked. They (me too) think like this,
> > "this function never fails".
> > So error handing is incomplete by definition.
>
> You don't need to check the error code if you can PROVE
> that the function never fails.
True, but in that case, the function no longer falls into the category
of "that must be checked" -- IOW, it's no longer within the realm upon
which he was commenting.
> > [4] Calling code may not have enough information
> > to correctly process error condition - in usual
> > (with fully-implemented error handling strategy :) )
> > program error will be reported to higher levels.
> > Careful programming required!
>
> This makes no sense. It could apply
> whether or not the C++ exception handling mechanism is used.
I believe what he's trying to point out is that lacking exception
handling, intermediate levels of code have to take an active part in
propagating error codes to higher levels to allow proper handling. The
language does nothing to enforce this, so the default at any point is
for the error code to be lost. With exception handling, propagation
becomes automatic, and active participation is needed only when you wish
to stop an exception from propagating.
> > [5] Why should I repeat almost equivalent error checking code in every
> > function, which will propagate errors to higher levels of the program.
>
> Why would you?
> Just return the exception object to the calling function.
Because nearly every level then has to sort out whether this is an
exception it can handle or not. Even code that has no interest in
exceptions requires, at bare minimum, code to receive and propagate the
exception.
[ ... ]
> What does this mean?
> How do C++ application programmers know which exceptions
> they should try to catch and handle?
By having a clue as to what they're doing.
[ ... ]
> This argument is invalid because you can return exception objects
> instead of throwing them.
How exactly would you do this in a situation such as an overloaded
operator? Consider code like:
a = b + c;
that uses something like:
some_type operator+(some_type const &a, some_type const &b) {
if ( a.invalid() || b.invalid())
throw invalid_operand();
return some_type(a.value + b.value);
}
Your job is to ensure that the "a = b + c;" line remain essentially
unchanged, but deal with things by returning exception objects instead
of throwing them.
--