From: Daniel T. on
"Nevin :-] Liber" <nevin(a)eviloverlord.com> wrote:
> "Daniel T." <daniel_t(a)earthlink.net> wrote:
>
> > In my experience (and it might be just in my domain,) if an
> > exception is thrown, then it is because a programmer made an
> > unwarranted assumption while writing some particular piece of code
> > and the code should be fixed so the exception is no longer thrown.
>
> (In my problem domain, you are describing ASSERT, not exceptions.)

Several people have made comments like this one. I can imagine a domain
where just asserting and aborting the program, or allowing a bug that
wasn't found during test time to put the program in an undefined state,
would be a very bad thing; such systems would use exceptions to do some
sort of reset and problem logging. However, that isn't my domain.

I style my code after the standard when it comes to exceptions. A thrown
exception means that the code that detected the programmer error, is not
the code that needs to be fixed. (Precondition violations.)

Some who responded like to use exceptions for normal control flow that
is designed to deal with user errors. I personally don't think that is
appropriate.

> I'm confused. In some of your examples, you use STL constructs (such
> as vector and string), which can throw. How do you avoid things like
> vector and string from throwing exceptions?

Good question. It's called being pro-active, for example:

I know that bad_alloc will not be thrown because I know how much memory
I have to work with, and I keep within that memory footprint. If
bac_alloc does get thrown, then that is a bug that must be fixed, not a
part of the normal control flow of the program.

I know that bad_cast will not be thrown because when I dynamic cast a
reference, I know it will succeed. If bad_cast does get thrown, then
that is a bug that must be fixed, not a part of the normal control flow
of the program.

I know that bad_typeid will not be thrown because when I get the typeid
of a dereferenced pointer, I know the pointer contains something. If
bad_typeid does get thrown, then that is a bug that must be fixed, not a
part of the normal control flow.

I could write a paragraph like the above for every single exception in
the standard (and every exception that my code throws,) but I'm sure you
get the idea.

(When working in a team, replace "I" with "We" in the above.)

Hopefully, this clears up my position on the issue.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Daniel T. on
Francis Glassborow <francis.glassborow(a)btinternet.com> wrote:

> One thing that irritates me with the SESE camp is that many of them
> actually do not understand that it is more than just avoiding multiple
> exits it is about structuring your code in such a way that a single exit
> is natural and not being contrived by having extra variables.
>
> And the SEME camp contains a good number of people whose code lacks
> clarity because they just bail out at any old point.

Thank you Francis for being the voice of reason. I think part of the
problem is the false dichotomy of the entire discussion. If I ever met a
programmer who *never* used multiple exits, or *never* used singe exits,
I would ignore him for a fool.

The goal is to structure the code well and I tend to structure my code
so that I don't *need* multiple exits. The only thing I do that is even
remotely controversial is that I tend to add a "result" variable. (As I
have already said in this thread, I do this because it makes testing
easier.) The people I've worked with routinely tell me that my code is
very readable (even people who don't like me will say that my code looks
"academic" or like a textbook example,) so I think I'm doing OK as far
as code structure is concerned.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Mathias Gaunard on
On Mar 5, 2:35 pm, "Daniel T." <danie...(a)earthlink.net> wrote:
> "Nevin :-] Liber" <ne...(a)eviloverlord.com> wrote:
>
> > "Daniel T." <danie...(a)earthlink.net> wrote:
>
> > > In my experience (and it might be just in my domain,) if an
> > > exception is thrown, then it is because a programmer made an
> > > unwarranted assumption while writing some particular piece of code
> > > and the code should be fixed so the exception is no longer thrown.
>
> > (In my problem domain, you are describing ASSERT, not exceptions.)
>
> Several people have made comments like this one. I can imagine a domain
> where just asserting and aborting the program, or allowing a bug that
> wasn't found during test time to put the program in an undefined state,
> would be a very bad thing; such systems would use exceptions to do some
> sort of reset and problem logging. However, that isn't my domain.
>
> I style my code after the standard when it comes to exceptions. A thrown
> exception means that the code that detected the programmer error, is not
> the code that needs to be fixed. (Precondition violations.)

Trying to allocate a resource and it failing is a programmer error?
Interesting point of view, but it doesn't work.

Exceptions are not for programming errors, there are for errors that
shouldn't happen ideally but may well happen anyway, and still need to
be correctly dealt with (at least, if you want to write code of decent
quality).

For programming errors, you use asserts, which abort the program if a
precondition has been violated, because the program is in a state it
definitely should never be in, and there is no way to recover from
that.



> I know that bad_alloc will not be thrown because I know how much memory
> I have to work with

No you don't.
You're likely working on a system with multiple processes running at
the same time, and there is no realistic way to predict whether memory
allocation would succeed or fail at a given time.

Normally, it shouldn't happen; but it may still happen, and you need
to deal with it cleanly.

(In truth, your operating system probably overcommits anyway, but that
wouldn't be the case for sensitive resources or on platforms where
memory is sensitive)


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Thomas Richter on
Daniel T. wrote:
> "Nevin :-] Liber" <nevin(a)eviloverlord.com> wrote:
>> "Daniel T." <daniel_t(a)earthlink.net> wrote:
>>
>>> In my experience (and it might be just in my domain,) if an
>>> exception is thrown, then it is because a programmer made an
>>> unwarranted assumption while writing some particular piece of code
>>> and the code should be fixed so the exception is no longer thrown.
>> (In my problem domain, you are describing ASSERT, not exceptions.)
>
> Several people have made comments like this one. I can imagine a domain
> where just asserting and aborting the program, or allowing a bug that
> wasn't found during test time to put the program in an undefined state,
> would be a very bad thing; such systems would use exceptions to do some
> sort of reset and problem logging. However, that isn't my domain.

Exceptions are rarely used to do some kind of "reset". They are
(probably) reported, or (probably) addressed by additional logic that
analyses the source of the problem and then addresses the problem.
Exceptions are a mechanism that, if point A in a program finds itself in
a situation it cannot handle by itself, this problem is reported
"upstream" by several layers to the caller to address it.

If point A could have fixed the issue, then it rather should do that
immediately without the need of reporting it.

If the condition is because the program is in an undefined state, then
throwing an exception is *not* a good idea. How do you want to fix a
problem if all you know is that the program state is *exactly not*
well-defined? That is, exceptions are *exactly not* to report undefined
program states. This is what assertions are good for.

Example for exceptions: An input file is in an invalid format. Report
the error to the user, or report the problem upstream to try a different
format.

Example for exceptions: An algorithm A is supposed on non-negative
inputs generated by a second algorithm B. The algorithm A finds a
negative number as input. Apparently, then B is buggy. Nothing else can
be done at this point. Terminate the program.

> I style my code after the standard when it comes to exceptions. A thrown
> exception means that the code that detected the programmer error, is not
> the code that needs to be fixed. (Precondition violations.)

Sorry, you misunderstand. Exceptions are, in the standard, not used to
report programmer errors; they are, in no sense, indications that
something in the code needs to be fixed.

> Some who responded like to use exceptions for normal control flow that
> is designed to deal with user errors. I personally don't think that is
> appropriate.

But that's exactly what exceptions are designed for. Without exceptions,
a user error would have to be reported upsteam by return codes. Which
means that every caller is *required* to check for return codes all the
time, which also means that you (often) cannot use the function return
value for anything *but* error codes. Which means code that is less
readable and less maintainable - this is *exactly* what exceptions address.

>> I'm confused. In some of your examples, you use STL constructs (such
>> as vector and string), which can throw. How do you avoid things like
>> vector and string from throwing exceptions?
>
> Good question. It's called being pro-active, for example:
>
> I know that bad_alloc will not be thrown because I know how much memory
> I have to work with, and I keep within that memory footprint. If
> bac_alloc does get thrown, then that is a bug that must be fixed, not a
> part of the normal control flow of the program.

I don't know the domain you're working in, but *usually* you neither
have algorithms whose memory footprint can be exactly predicted, nor are
you working in environments whose available memory is known exactly in
advance. The former applies only to trivial problems, the latter might
probably be true in embedded applications. But every multithreading
operating system is, by construction, non-deterministic, so you cannot
know in advance whether memory will be available or not at a certain point.

> I know that bad_cast will not be thrown because when I dynamic cast a
> reference, I know it will succeed. If bad_cast does get thrown, then
> that is a bug that must be fixed, not a part of the normal control flow
> of the program.

Simple enough to avoid, but bad_cast is not necessary a "bug". It might
also be used to filter out "untypical" input, i.e. the exception could
be cought and the input could be handled in some other type. If that is
not the case, let the exception unwind up to main() where an unexpected
exception will be reported and the program will terminate.

> I know that bad_typeid will not be thrown because when I get the typeid
> of a dereferenced pointer, I know the pointer contains something. If
> bad_typeid does get thrown, then that is a bug that must be fixed, not a
> part of the normal control flow.

See above. Not necessarily so. If bad_typeid is thrown and that is *not*
part of the designed program flow, then the program should be terminated.

> I could write a paragraph like the above for every single exception in
> the standard (and every exception that my code throws,) but I'm sure you
> get the idea.

No. I don't, sorry. I have the strange feeling that you got "exceptions"
backwards. "exceptions" are something very different from "assertions"
and program bugs. They are a useful construction for *correct* but
*rare* global flow control of an algorithm, to address situations were
you do not want to pass return codes through several layers of code.

Exceptions are rather ill-designed to report program bugs because you
could still catch them and continue going.

So long,
Thomas



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Mathias Gaunard on
On 6 mar, 02:09, Thomas Richter <t...(a)math.tu-berlin.de> wrote:

> Exceptions are rarely used to do some kind of "reset". They are
> (probably) reported, or (probably) addressed by additional logic that
> analyses the source of the problem and then addresses the problem.
> Exceptions are a mechanism that, if point A in a program finds itself in
> a situation it cannot handle by itself, this problem is reported
> "upstream" by several layers to the caller to address it.

Exceptions are not just a mere way of reporting errors to upper
layers. They also allow to properly cancel whatever current operations
the exception happened in the middle of, assuming your code is
exception-safe. (what cancel exactly means depends on the level of
exception-safety)

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]