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

A good error case practice

72 views
Skip to first unread message

JiiPee

unread,
Aug 21, 2015, 1:23:54 PM8/21/15
to
If a code is done well, should it have error checking in all places? But
if you do that everywhere the code is filled with try-catch, isnt it?

For example if I resize an array should I always there use try-catch to
check an error situation in a professional code? Because its always
possible with new vector allocation that the memory was full.

I guess the try-catch block should be put to everywhere where an
exception can be thrown, right?

Paavo Helde

unread,
Aug 21, 2015, 1:54:43 PM8/21/15
to
JiiPee <n...@notvalid.com> wrote in news:s8JBx.257668$pi.9...@fx47.am4:
Absolutely not! This would defeat the whole purpose of exceptions.

You put a try-catch in a place where you know how to handle the error. For
many programs this means a single try-catch in main() where you report the
error and exit the program with an error exit code.

hth
Paavo

Victor Bazarov

unread,
Aug 21, 2015, 1:56:54 PM8/21/15
to
No.

There should be very few places in your code that are surrounded with
'try' and have a 'catch' supplied, IMHO. The subject of error checking
or how/where/whether to respond to abnormal situations is too vast for
even a newsgroup thread. Have you tried looking for a book? Also, this
is more of a software engineering topic than a language topic. Perhaps
you could ask in 'comp.software-eng'? If they are no longer active, try
looking on the web.

V
--
I do not respond to top-posted replies, please don't ask

JiiPee

unread,
Aug 21, 2015, 2:11:55 PM8/21/15
to
You mean that its a pretty good approach (especially with small
programs) just to wrap around the whole code with try-catch. Then if any
part throws this catches all of them? And then one can add try-catch
blocks if there is a special need to somewhere else as well?

Chris M. Thomasson

unread,
Aug 21, 2015, 3:39:24 PM8/21/15
to
> "Stefan Ram" wrote in message
> news:exception-20...@ram.dialup.fu-berlin.de...

[...]

> An important subject that often is missing from text books:
> RAII won't work without a global try-catch!

You mean that dtors just might not be called if an exception is thrown
without a
global try-catch?

Humm... I did not know that!

Yikes!

;^o

[...]

Paavo Helde

unread,
Aug 21, 2015, 4:00:21 PM8/21/15
to
JiiPee <n...@notvalid.com> wrote in news:xRJBx.214272$bt.4...@fx32.am4:
Exactly. Do not catch the exception if you have no idea what to do with
it. For example, putting a try-catch around each vector push_back would
be of no use because you do not know how to handle it, it's too low-level
code. This is the decision of the application, not of the low-level
library code doing push_backs.

For example, imagine an image processing program, it can easily run out
of memory deep in some image transformation algorithm which has no idea
from which application it is called from and what would be a sensible
remedy. If it is a non-GUI program then probably the most sensible way is
to have one try-catch in main() and exit the process, if it is a GUI()
program then it might make sense to put try-catch in the main GUI event
loop and notify the user that an action failed and he can try to do
something else. (Though to be honest, memory exhaustion is pretty fatal,
even if your program survives it there is no guarantee that other
programs and the OS will cope with it properly.)

Cheers
Paavo


Richard

unread,
Aug 21, 2015, 4:34:39 PM8/21/15
to
[Please do not mail me a copy of your followup]

n...@notvalid.com spake the secret code
<s8JBx.257668$pi.9...@fx47.am4> thusly:

>If a code is done well, should it have error checking in all places?

It should have error *detection* at all the places where errors can be
detected. Usually this is from C style APIs that indicate errors by
return value because C doesn't have exceptions.

Let's take a concrete example. In COM programming, methods on COM
interfaces and COM global functions return HRESULT status codes
indicating success or failure. In some cases, an HRESULT may be
tested explicitly because it is "normal" for it to fail -- for
instance opening a file whose name is supplied on the command-line
arguments or through other user input. The user may have simply typed
the filename incorrectly and we want to handle the "can't open file"
error explicitly. In this case, failure is an expected part of normal
interaction.

In other cases, the failure is due to a programming error and we
aren't going to build user interface or other specific handling for
this error, but we don't want to ignore it either. In this case,
errors are exceptional and not a part of normal interaction.

In my book on Direct3D programming, I showed a technique for mapping
unexpected COM HRESULT failures to C++ exceptions so that your code
has good error detection, the error detection is pushed behind a
simple mechanism that doesn't obscure normal flow, and such errors are
immediately brought to your attention when they occur instead of the
errors accumulating behind the scenes.

See section 1.13 Code Techniques on pg. 25 of the PDF:
<http://user.xmission.com/~legalize/book/download/01-Introduction.pdf>

>But
>if you do that everywhere the code is filled with try-catch, isnt it?

If your code is littered with try-catch blocks, then IMO you haven't
identified your error handling strategy and have approached things in
a haphazard manner.

>For example if I resize an array should I always there use try-catch to
>check an error situation in a professional code? Because its always
>possible with new vector allocation that the memory was full.

Full or fragmented and the requested size couldn't be obtained as a
single contiguous chunk. The question is: What should I do about
bad_alloc exceptions?

For many (most?) applications, the answer is "nothing, really". If
your code was written to be exception safe, then unwinding everything
all the way out to main should gracefully release all resources
acquired so far and then call std::terminate.
<http://en.cppreference.com/w/cpp/error/terminate>

There are other applications where a reasonable strategy for handling
std::bad_alloc is to capture it somewhere within an interactive GUI
processing event loop and abort an in-progress operation cleanly,
informing the user that the requested operation could not be completed
because of insufficient memory.

>I guess the try-catch block should be put to everywhere where an
>exception can be thrown, right?

Again, the question that should be asked here is: what is my error
(exception) handling policy? Where, if anywhere, can or should I
handle unexpected exceptions? Depending on the code you are writing,
the answer can be very different.

If I am writing a library and my callers may be from C or some other
language that doesn't support C++ exceptions, then I shouldn't allow
any C++ exceptions to unwind out of any of my external API entry
points. I should catch all exceptions and turn them into some kind of
C style error code that can be inspected by the caller.

If I am writing a library intended only to be used from C++, I might
allow exceptions to unwind from my library. However, even here it is
not a rule -- even the standard library has different strategies for
different components. For instance, attempting to extract an int from
an istream that is empty doesn't result in an exception. Even
attempting to open an ifstream on a non-existent file doesn't throw an
exception.

The filesystem technical specification generally provides two forms of
operations like "copy_file": one that throws on error and another that
returns an error code on failure. This leaves the choice of the error
handling mechanism up to the caller, but either way the copy_file
operation detects errors.
<http://en.cppreference.com/w/cpp/experimental/fs/copy_file>

My general rule of thumbs are:

- understand what, if any, error/exception handling strategy your
application should have and then look for the fewest number of places
to apply the error/exception handling. Usually that is just a small
handfull of places. If you're doing a try/catch around every
expression that could potentially throw, you're doing it wrong.
- decide on the error handling policy for all subsystems (should
exceptions throw across the library boundary, for instance?)
- turn all C style error codes into C++ exceptions when the underlying
API call shouldn't fail in the normal course of operation. Let them
break your application.
- most GUI frameworks don't like it when event handlers throw
exceptions up into the GUI framework, so consider "GUI framework
event handlers" to be living at the boundary between systems.
- bad_alloc usually indicates such catastrophic failure that there
usually isn't much you can do about it besides exit which is what will
happen anyway. However, interactive applications may want to
provide the user with one last chance to save unsaved work. This,
in turn, may also fail if it needs to allocate memory in order to
save work.
- avoid C style error status codes for most things and instead prefer
exceptions for unusual/exceptional errors
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Richard

unread,
Aug 21, 2015, 4:42:57 PM8/21/15
to
[Please do not mail me a copy of your followup]

"Chris M. Thomasson" <nos...@nospam.nospam> spake the secret code
<mr7uop$6nc$1...@speranza.aioe.org> thusly:

>You mean that dtors just might not be called if an exception is thrown
>without a global try-catch?

The standard says it is implementation defined whether or not the
stack is unwound before calling std::terminate. It doesn't explain
why this is allowed to be defined by the implementation.

JiiPee

unread,
Aug 21, 2015, 6:38:41 PM8/21/15
to
On 21/08/2015 20:20, Stefan Ram wrote:
> ...So this shows that books and the web are fine, but to really learn
> what matters, one Must Read The Usenet!

Thanks, interesting things

Paavo Helde

unread,
Aug 22, 2015, 3:13:46 AM8/22/15
to
JiiPee <n...@notvalid.com> wrote in news:FLNBx.282793$8E7.1...@fx29.am4:
In this case, the knowledge comes from the C++ standard, and the standard
(at least the final draft) is available in the web:

15.5.1/2: "In the situation where no matching handler is found,
it is implementation-defined whether or not the stack is unwound before
std::terminate() is called."

This also shows that Usenet was not really precise when calling the
behavior "unspecified" as this is a bit different from "implementation-
defined".

Cheers
Paavo

Juha Nieminen

unread,
Aug 24, 2015, 8:43:08 AM8/24/15
to
Paavo Helde <myfir...@osa.pri.ee> wrote:
> You put a try-catch in a place where you know how to handle the error. For
> many programs this means a single try-catch in main() where you report the
> error and exit the program with an error exit code.

There are environments where you can't exit cleanly from main().
(For example iOS. If main() is exited, the system considers the
program having crashed.)

--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---

Jorgen Grahn

unread,
Sep 16, 2015, 6:15:10 PM9/16/15
to
On Fri, 2015-08-21, Stefan Ram wrote:
...

> An important subject that often is missing from text books:
> RAII won't work without a global try-catch! I learned it from
> the Usenet, where I was told:
>
> »It's unspecified whether stack unwinding happens when
> there is no handler for an exception.«

I don't quite see how you go from that to "RAII won't work without a
global try-catch". Without one, you'll have an unknown number of code
paths where destructors aren't run before a crash, but you'll have
that anyway for assert() and std::exit() calls, and for pure crashes.

And RAII still works for all other code paths.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
0 new messages