catch (...)

B

Bit byte

Is there any way of retrievieng error information (say, from a 'global'
or system wide) error object - when you are in a catch all statement block?

Sometimes it cannot be helped, when something quirky happens and errors
are propagated up the stack - all the way to the 'one size fits all'
catch (...) statement. It would be useful if there is a way of finding
what srewy thing happened and led us to that point.
 
M

mlimber

Bit said:
Is there any way of retrievieng error information (say, from a 'global'
or system wide) error object - when you are in a catch all statement block?

Sometimes it cannot be helped, when something quirky happens and errors
are propagated up the stack - all the way to the 'one size fits all'
catch (...) statement. It would be useful if there is a way of finding
what srewy thing happened and led us to that point.

Sure, if that global error object was properly set before the exception
was thrown (cf. errno). You won't get any information out of the
exception itself (e.g., it's type or a message from
std::exception::what()) since there is no specific exception caught in
a catch-all.

<OT>Some platforms (notably Microsoft) throw "exceptions" for other
errors such as access violations resulting from a wayward pointer.
(Microsoft calls this structure exception handling (SEH). See
http://www.boost.org/more/error_handling.html on how to mitigate SEH's
interference with the debugger.) If that's what you're referring to,
you should ask in a newsgroup for your platform.</OT>

Cheers! --M
 
A

Alf P. Steinbach

* mlimber:
Sure, if that global error object was properly set before the exception
was thrown (cf. errno). You won't get any information out of the
exception itself (e.g., it's type or a message from
std::exception::what()) since there is no specific exception caught in
a catch-all.

On the contrary, there is a specific exception caught in a catch-all.

Try

#include <cstddef>
#include <stdexcept>
#include <iostream>
#include <ostream>

int main()
{
try
{
throw std::runtime_error( "Indeed" );
}
catch( ... )
{
try
{
throw;
}
catch( std::exception const& x )
{
std::cerr << "!" << x.what() << std::endl;
}
catch( ... )
{
std::cerr << "!Unknown exception" << std::endl;
}
return EXIT_FAILURE;
}
}

Modulo typos, of course; also, won't work with older compilers like VC6.

The inner try-catch can be moved to a separate function.
 
P

Phlip

Bit said:
Is there any way of retrievieng error information (say, from a 'global'
or system wide) error object - when you are in a catch all statement
block?

No.

As Alf pointed out, you can still find a way to access the thing thrown - if
you know its type. In which case, this would suffice:

try { allMyProgram(); }
catch( std::exception & e )
{
cout << whatever;
}
catch(...)
{
cout << whatever;
}

So now the question is how to minimize the impact of an unhandled exception
on your customers. Your program should write a log file that optionally
records each program activity. When the program faults take its log file
and write an acceptance test that produces a similar log file.

As you near the problem, use a debugger with an [off-topic] feature to
breakpoint each 'throw' statement, to find out which one it was.

If you use MS Windows, check with their newsgroups to learn how to catch the
special structured exceptions their OS throws. These are different, but
catch(...) can catch them.
 
P

Phlip

Bit said:
Is there any way of retrievieng error information (say, from a 'global'
or system wide) error object - when you are in a catch all statement
block?

No.

As Alf pointed out, you can still find a way to access the thing thrown - if
you know its type. In which case, this would suffice:

try { allMyProgram(); }
catch( std::exception & e )
{
cout << whatever;
}
catch(...)
{
cout << whatever;
}

So now the question is how to minimize the impact of an unhandled exception
on your customers. Your program should write a log file that optionally
records each program activity. When the program crashes take its log file
and write an acceptance test that produces a similar log file.

As you near the problem, use a debugger with an [off-topic] feature to
breakpoint each 'throw' statement, to find out which one it was.

If you use MS Windows, check with their newsgroups to learn how to catch the
special structured exceptions their OS throws. These are different, but
catch(...) can catch them.
 
B

benben

Alf said:
* mlimber:

On the contrary, there is a specific exception caught in a catch-all.

Try

#include <cstddef>
#include <stdexcept>
#include <iostream>
#include <ostream>

int main()
{
try
{
throw std::runtime_error( "Indeed" );
}
catch( ... )
{
try
{
throw;
}
catch( std::exception const& x )
{
std::cerr << "!" << x.what() << std::endl;
}
catch( ... )
{
std::cerr << "!Unknown exception" << std::endl;
}
return EXIT_FAILURE;
}
}

Inspiring! But I guess the reason why the OP only catches the exception
in (...) in the first place, is that the exception thrown wasn't even an
std::exception.
Modulo typos, of course; also, won't work with older compilers like VC6.

The inner try-catch can be moved to a separate function.

Regards,
Ben
 
C

Cy Edmunds

Alf P. Steinbach said:
* mlimber:

On the contrary, there is a specific exception caught in a catch-all.

Try

#include <cstddef>
#include <stdexcept>
#include <iostream>
#include <ostream>

int main()
{
try
{
throw std::runtime_error( "Indeed" );
}
catch( ... )
{
try
{
throw;
}
catch( std::exception const& x )
{
std::cerr << "!" << x.what() << std::endl;
}
catch( ... )
{
std::cerr << "!Unknown exception" << std::endl;
}
return EXIT_FAILURE;
}
}

Modulo typos, of course; also, won't work with older compilers like VC6.

The inner try-catch can be moved to a separate function.

Right! This tip really helped me with a project I'm working on. Thanks!

Cy
 
P

Phlip

Cy said:
Right! This tip really helped me with a project I'm working on. Thanks!

That tip is a super-complex way to simply say this:

try
{
throw std::runtime_error( "Indeed" );
}
catch( std::exception const& x )
{
std::cerr << "!" << x.what() << std::endl;
return EXIT_FAILURE;
}
catch( ... )
{
std::cerr << "!Unknown exception" << std::endl;
return EXIT_FAILURE;
}
 
A

Alf P. Steinbach

* Phlip:
That tip is a super-complex way to simply say this:

try
{
throw std::runtime_error( "Indeed" );
}
catch( std::exception const& x )
{
std::cerr << "!" << x.what() << std::endl;
return EXIT_FAILURE;
}
catch( ... )
{
std::cerr << "!Unknown exception" << std::endl;
return EXIT_FAILURE;
}

No.

Mostly, the technique is applicable when you have several different
exception types originating from various third-part libraries.

Placing a multiple try-catch like the above in every function really
isn't an option, and using macros to generate such beasties isn't a very
clean solution. A separate exception conversion function is then a
relatively clean way to deal with the exceptions. All it requires is a
catch-all in each function that deals directly with lib functions.
 
P

Phlip

Alf said:
* Phlip:

No.

As written, yes. The place where we wrote "throw std::runtime_error..."
could have been the rest of the program. Either one top-level handler, or
the other, will catch things by type, and catch everything else without its
type.
Mostly, the technique is applicable when you have several different
exception types originating from various third-part libraries.

Placing a multiple try-catch like the above in every function really
isn't an option,

Nobody said anything about putting the handlers in every function.
and using macros to generate such beasties isn't a very
clean solution.

Nobody said we would abuse macros.
A separate exception conversion function is then a
relatively clean way to deal with the exceptions. All it requires is a
catch-all in each function that deals directly with lib functions.

It's now possible you mean this:

catch(...) {
caught();
}

void caught()
{
try
{
throw;
}
catch( std::exception const& x )
{
std::cerr << "!" << x.what() << std::endl;
}
catch( ... )
{
std::cerr << "!Unknown exception" << std::endl;
}

}

Now we can re-use caught() all over the place. Props.
 
M

mlimber

Alf said:
* Phlip:

No.

Mostly, the technique is applicable when you have several different
exception types originating from various third-part libraries.

Placing a multiple try-catch like the above in every function really
isn't an option, and using macros to generate such beasties isn't a very
clean solution. A separate exception conversion function is then a
relatively clean way to deal with the exceptions. All it requires is a
catch-all in each function that deals directly with lib functions.

I agree that using a conversion function such as this is cleaner in
some cases, but logically there is no difference between yours and
Phlip's code -- they both can catch the desired exception types and
give up on others. In the catch-all block of your handler, you still
don't have any information on the "other" exception (except that it is
not one of the explicitly caught types), which is presumably the same
situation the OP is in to begin with.

Cheers! --M
 
A

Alf P. Steinbach

* mlimber:
I agree that using a conversion function such as this is cleaner in
some cases, but logically there is no difference between yours and
Phlip's code -- they both can catch the desired exception types and
give up on others.

Feel free to use assembly language.

Or manually inline expanded code.

After all any C++ program can be expressed (a bit more verbosely) in
assembly language, and actually assembly language is a bit more powerful
in what can be done -- it's the logical choice! :-o

In the catch-all block of your handler, you still
don't have any information on the "other" exception (except that it is
not one of the explicitly caught types), which is presumably the same
situation the OP is in to begin with.

Only the OP can clarify whether this technique is useful to him or her.

This wasn't written in response to the OP.
 
M

mlimber

Alf said:
* mlimber:

Feel free to use assembly language.

Or manually inline expanded code.

After all any C++ program can be expressed (a bit more verbosely) in
assembly language, and actually assembly language is a bit more powerful
in what can be done -- it's the logical choice! :-o

I agree whole-heartedly that the efficiency issues here are not to be
ignored, but my point remains unchallenged: the two code snippets have
the same *logical* effect and by using your (admittedly nifty) trick,
the programmer doesn't gain any information that s/he couldn't have
gotten by adding the same handlers before the catch-all.
Only the OP can clarify whether this technique is useful to him or her.

The problem as I read it was that the OP wanted to get some information
from an unknown exception that was caught. Aside from adding specific
handlers (whether before the catch-all or in a separate function),
there is no way to do this.

Cheers! --M
 
P

Phlip

mlimber said:
I agree whole-heartedly that the efficiency issues here are not to be
ignored, but my point remains unchallenged: the two code snippets have
the same *logical* effect and by using your (admittedly nifty) trick,
the programmer doesn't gain any information that s/he couldn't have
gotten by adding the same handlers before the catch-all.

I have no idea what Alf's complaining about, but my version (with caught())
showed how only Alf's code can put the catchers inside a reusable function.
This is a nice technique, iff you have too many exceptions (!!), and iff
you handle them in too many places (!!).
The problem as I read it was that the OP wanted to get some information
from an unknown exception that was caught. Aside from adding specific
handlers (whether before the catch-all or in a separate function),
there is no way to do this.

Hence my original post, to write a coherent log file and such general
robustness techniques...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,129
Latest member
FastBurnketo
Top