Can I always determine what I catch?

  • Thread starter Steven T. Hatton
  • Start date
S

Steven T. Hatton

If I understand correctly, I have no assurance that I can determine the type
of a simple class instance thrown as an exception unless I explicitly catch
it by name. (non-derived classes having no virtual funcitons have no rtti)
That is, there is no way to do something like:
try{
funct_from_3rd_party();
}
catch(...){
std:err << extract_name() << std::endl;
}

Is this correct? Do I even have a way to access the object caught in a
catch(...)?
 
V

Victor Bazarov

Steven T. Hatton said:
If I understand correctly, I have no assurance that I can determine the type
of a simple class instance thrown as an exception unless I explicitly catch
it by name. (non-derived classes having no virtual funcitons have no rtti)
That is, there is no way to do something like:
try{
funct_from_3rd_party();
}
catch(...){
std:err << extract_name() << std::endl;
}

Is this correct? Do I even have a way to access the object caught in a
catch(...)?

Not in any standard way. If you want to catch something particular, like
a descendant of std::exception, then catch 'std::exception' by reference,
then you at least have a shot at calling 'what()' in hope that they managed
to implement it correctly.

OTOH, if they (the 3rd party) didn't document their exceptions at all, there
is no way to know what they throw and when. Contact them and ask for some
kind of documentation (or at least the source code where they have 'throw'
expressions and statements).

Victor
 
A

Alf P. Steinbach

* Steven T. Hatton:
If I understand correctly, I have no assurance that I can determine the type
of a simple class instance thrown as an exception unless I explicitly catch
it by name. (non-derived classes having no virtual funcitons have no rtti)
That is, there is no way to do something like:
try{
funct_from_3rd_party();
}
catch(...){
std:err << extract_name() << std::endl;
}

Is this correct?
No.


Do I even have a way to access the object caught in a catch(...)?

Yes.
 
S

Steven T. Hatton

Alf said:
* Steven T. Hatton:

Yes.

Ok, I give. How can I write a function to extract type information from an
arbitrary exception? How can I get a handle on an arbitrary exception
object caught in a catch(...) handler? The listing below is the kind of
thing I've been trying without success. The specific example is from IBM's
documentation found here:

http://publib.boulder.ibm.com/infoc...cpp6a.doc/language/ref/exceptions.cplr162.htm

I only added the second output line in the catch(bad_exception) handler.
I've tried many other things along these lines.

#include <exception>
#include <iostream>

using namespace std;

class X { };
class Y { };
class A { };

// pfv type is pointer to function returning void
typedef void (*pfv)();

void my_terminate() {
cout << "Call to my terminate" << endl;
abort();
}

void my_unexpected() {
cout << "Call to my_unexpected()" << endl;
throw;
}

void f() throw(X,Y, bad_exception) {
throw A();
}

void g() throw(X,Y) {
throw A();
}

int main()
{
pfv old_term = set_terminate(my_terminate);
pfv old_unex = set_unexpected(my_unexpected);
try {
cout << "In first try block" << endl;
f();
}
catch(X) {
cout << "Caught X" << endl;
}
catch(Y) {
cout << "Caught Y" << endl;
}
catch (bad_exception& e1) {
cout << "Caught bad_exception" << endl;
cout << "bad_exception = " << e1.what() << endl;
}
catch (...) {
cout << "Caught some exception" << endl;
}

cout << endl;

try {
cout << "In second try block" << endl;
g();
}
catch(X) {
cout << "Caught X" << endl;
}
catch(Y) {
cout << "Caught Y" << endl;
}
catch (bad_exception& e2) {
cout << "Caught bad_exception" << endl;
cout << "bad_exception"<< e2.what() << endl;
}
catch (...) {
cout << "Caught some exception" << endl;
}
}
 
A

Alf P. Steinbach

* Steven T. Hatton:
How can I get a handle on an arbitrary exception object caught in
a catch(...) handler?

'handle': no such thing in the C++ language.

You can determine the type from a set of known possible types by
rethrowing and catching, and you can do that in a function called
from the "..." handler.

The statement 'throw;' will rethrow the exception, whatever it is.
 
R

Richard Herring

Steven T. Hatton said:
If I understand correctly, I have no assurance that I can determine the type
of a simple class instance thrown as an exception unless I explicitly catch
it by name. (non-derived classes having no virtual funcitons have no rtti)

That last bit is not the case. The compiler can (and does) wrap
non-polymorphic thrown objects in something that carries the necessary
type information to disambiguate catch() clauses, so you can even throw
and catch built-in types if you really want to.
That is, there is no way to do something like:
try{
funct_from_3rd_party();
}
catch(...){
std:err << extract_name() << std::endl;
}

but that is true.
Is this correct? Do I even have a way to access the object caught in a
catch(...)?

Only if you can enumerate all the types it might take, which obviously
requires additional information about the 3rd-party function.
 
R

Ron Natalie

Richard Herring said:
That last bit is not the case. The compiler can (and does) wrap
non-polymorphic thrown objects in something that carries the necessary
type information to disambiguate catch() clauses, so you can even throw
and catch built-in types if you really want to.

Actually, it's an implementation issue. However, since polymorphism has
no meaning to exceptions, it pretty much has to do the same thing in any
case. It actually doesn't necessarily have to "wrap" anything. It only
has to remember the static type of the object thrown as it is unwinding
the stack. The language punts on the issue of two exceptions being handled
at the same time.
 
S

Steven T. Hatton

Alf said:
* Steven T. Hatton:

'handle': no such thing in the C++ language.

You can determine the type from a set of known possible types by
rethrowing and catching, and you can do that in a function called
from the "..." handler.

The statement 'throw;' will rethrow the exception, whatever it is.

So I catch an exception of unknown type which I don't have a handle on.
That was the fix I was in in the first place. Stroustrup tells us in
TC++PL(SE) §14.6.3.2 how to get a handle on a name exception. "Re-throwing
an exception and catching it allows us to get a handle on any exception of
a type we can name." But I don't know the name of the type!
 
A

Alf P. Steinbach

* Steven T. Hatton:
So I catch an exception of unknown type which I don't have a handle on.
That was the fix I was in in the first place. Stroustrup tells us in
TC++PL(SE) §14.6.3.2 how to get a handle on a name exception. "Re-throwing
an exception and catching it allows us to get a handle on any exception of
a type we can name." But I don't know the name of the type!

If you don't know anything about the type (i.e. not even a set of types it
could be from), what are you intending to do with it?
 
S

Steven T. Hatton

Alf said:
* Steven T. Hatton:

If you don't know anything about the type (i.e. not even a set of types it
could be from), what are you intending to do with it?

For starters, I thought it would be nice just to print it out to see what
the heck it is. I might want to log it, or use it for diagnostics in
troubleshooting. I would like to have a more convenient way of determining
that I can't get any further information from the exception. Something
along the lines of bad_exception, but that I could simply access in the
catch(...) block. The whole idea of throwing an int anonymously from a
function call seems wrong. There may be an argument for it in terms of
performance, but it better be a damn good one if someone wants to sell the
idea to me.

It's not clear to me if std::exception is intended to be extended beyond the
Standard Library. It sure seems a lot more intelligent than throwing
something completely unintelligible. At least there should be a way for
the language to /pretend/ it caught something like an object with a
queryable interface. Even if the only answer it gives is "beats me".
 
V

Victor Bazarov

Steven said:
Alf P. Steinbach wrote:




For starters, I thought it would be nice just to print it out to see what
the heck it is.

It would be, probably. Do all your classes provide the ability to
be printed out? So, why do you think that somebody else's should?
I might want to log it, or use it for diagnostics in
troubleshooting. I would like to have a more convenient way of determining
that I can't get any further information from the exception.

But you already have that. If catch(...) clause is entered, then you
can log "undefined exception has occurred, no further information is
available".
Something
along the lines of bad_exception, but that I could simply access in the
catch(...) block.

Why can't you have a catch (std::bad_exception&) for that? Why does it
have to be in catch(...) ?
The whole idea of throwing an int anonymously from a
function call seems wrong.

Probably. But that's what catch(...) is for. Catch anything somebody
may have thrown wrong. Nothing else can be done about it. If they didn't
do anything wrong, we wouldn't need catch(...) clause.
There may be an argument for it in terms of
performance, but it better be a damn good one if someone wants to sell the
idea to me.

Nobody wants to sell you anything. If you don't like a certain feature
of the language, you don't have to use it, now, do you?
It's not clear to me if std::exception is intended to be extended beyond the
Standard Library.

Why is it unclear? Of course it is intended. It even has virtual
functions so you could override certain behaviours.
It sure seems a lot more intelligent than throwing
something completely unintelligible.

Your OS may not be implemented in C++, so it's not necessarily correct to
assume that all third-party libraries (and your OS is one of them) _can_
throw something intelligible.
At least there should be a way for
the language to /pretend/ it caught something like an object with a
queryable interface. Even if the only answer it gives is "beats me".

I think you're making way too many assumptions and being inconsistent at
that. Why should _they_ provide you with "beats me" when you can do it
yourself:

try {
// whatever
..
}
catch (std::exception& e) {
cout << e.what(); // intelligible
}
catch (...) {
cout << "beats me";
}

Victor
 
A

Alf P. Steinbach

* Steven T. Hatton:
For starters, I thought it would be nice just to print it out to see what
the heck it is.

It might not have conversion to string, and if it has, by your own assumption
you don't know how to invoke that.

I might want to log it

That's easy: log "unknown exception".

or use it for diagnostics in troubleshooting.

That's what debuggers are for.

I would like to have a more convenient way of determining
that I can't get any further information from the exception. Something
along the lines of bad_exception, but that I could simply access in the
catch(...) block.

You have and I told you how; all you need to do is wrap it up in a function.

It's not clear to me if std::exception is intended to be extended beyond the
Standard Library.

It is, and you can see that simply from the fact that it has a virtual
function.
 
S

Steven T. Hatton

Victor said:
It would be, probably. Do all your classes provide the ability to
be printed out? So, why do you think that somebody else's should?

If all exceptions derived explicitly or implicitly from a single
über-exception, there would be no burden placed the developer in order to
accomplish this goal. You ask if all my classes can be printed. Well,
since a lot of what I'm currently doing is with Qt, the answer is: a lot of
them do. There is also my very first C++ interface class.

#ifndef STRINGABLE_H
#define STRINGABLE_H
#include <iosfwd>

using std::eek:stream;

/**
An un-universal base class
*/
namespace sth
{
class Stringable
{
public:
virtual ostream& stringify(ostream& out) const = 0;
};

inline ostream& operator<<(ostream& out, Stringable& s)
{
s.stringify(out);
return out;
}
}
#endif


But you already have that. If catch(...) clause is entered, then you
can log "undefined exception has occurred, no further information is
available".

And if everybody derives all exceptions from std::exception, the world would
be a better place. My impression of std::exception is that it was
originally intended to be used within the Standard Library. I haven't
given full consideration to the consequences of using it as the
Shah-an-Shah of exceptions. I favor making that, or something similar, a
requirement for exceptions. Of course there should be a means of changing
the default behavior through something along the lines of
std::set_unexpected().
Why can't you have a catch (std::bad_exception&) for that? Why does it
have to be in catch(...) ?

That may be an answer, but I'm not sure it would accomplish the same thing.
It's not clear to me when std::bad_exception is actually thrown. If this
means replacing the default unexpected handler to re-throw, and then catch
the exception as bad_exception, people are unlikely to use it.

It's hard to learn to use C++ exceptions correctly. This is the kind of
thing people are likely to avoid learing until they are either forced to,
or they master enough of the core language to begin investigating the
esoterica. IOW, people aren't going to use it, and if they do, they are
likely not to use it well.
Probably. But that's what catch(...) is for. Catch anything somebody
may have thrown wrong. Nothing else can be done about it. If they didn't
do anything wrong, we wouldn't need catch(...) clause.

Is that a reflection upon the developer or upon the exception facility
within C++? I really believe a few minor tweaks to the default behavior
described in the Standard would make exceptions much easier to use, and
therefor, much more commonly used. I tend to believe exceptions are a good
design mechanism which is fairly neglected in real-world C++ code.
Nobody wants to sell you anything. If you don't like a certain feature
of the language, you don't have to use it, now, do you?

If it were just me, I could control the situation. But this is the kind of
issue that impacts the usability of the language in general.
Why is it unclear? Of course it is intended. It even has virtual
functions so you could override certain behaviours.

§18.6.1 ¶1 "The class exception defines the base class for the types of
objects thrown as exceptions by C++ Standard library components, and
certain expressions, to report errors detected during program execution."
Your OS may not be implemented in C++, so it's not necessarily correct to
assume that all third-party libraries (and your OS is one of them) _can_
throw something intelligible.

Perhaps there should be a means of catching foreign exceptions.
I think you're making way too many assumptions and being inconsistent at
that. Why should _they_ provide you with "beats me" when you can do it
yourself:

try {
// whatever
..
}
catch (std::exception& e) {
cout << e.what(); // intelligible
}
catch (...) {
cout << "beats me";
}

If the default behavior were to require all exceptions be derived from
std::exception, that would be a far more obvious approach.
 
P

Peter van Merkerk

Victor said:
But you already have that. If catch(...) clause is entered, then you
can log "undefined exception has occurred, no further information is
available".

Another way to say it would be:
"Something went wrong.
We won't tell you where or why.
- Lazy Programmers"
 
S

Steven T. Hatton

Steven T. Hatton wrote:
[snip...]
The two biggest objections I have to the current form of C++ exception
handling are:

1) I don't know what I'm likely to catch. So I propose requiering that, by
default, all exceptions should be derived from std::exception (or a
suitable, similar class.)


2) I don't know what, if any exceptions a funciton is likely to throw, if
there is no (throw) in the function signature. (I'm not sure if that is
technically part of the signature - but it aughta be!) So I propose that,
by default, all function that might throw an exception should be requiered
to state that they throw an exception, and what kind. Either by explicitly
enumerating the possible types, or by nameing (a) baseclass(es) of all
exceptions thrown. If a function does not catch and handle an exception
thrown by a call it invokes, it must decare that it might throw that kind
of exception, or a suitable base class.



The following suggests there may be no fundamental reason C++ could not have
a more coherent exception mechanism.

http://es-sun2.fernuni-hagen.de/cgi-bin/info2html?(gcc)Java Exceptions
Java Exceptions
===============

The Java language uses a slightly different exception handling model
from C++. Normally, GNU C++ will automatically detect when you are
writing C++ code that uses Java exceptions, and handle them
appropriately. However, if C++ code only needs to execute destructors
when Java exceptions are thrown through it, GCC will guess incorrectly.
Sample problematic code is:

struct S { ~S(); };
extern void bar(); // is written in Java, and may throw
exceptions
void foo()
{
S s;
bar();
}

The usual effect of an incorrect guess is a link failure, complaining of
a missing routine called `__gxx_personality_v0'.

You can inform the compiler that Java exceptions are to be used in a
translation unit, irrespective of what it might think, by writing
`#pragma GCC java_exceptions' at the head of the file. This `#pragma'
must appear before any functions that throw or catch exceptions, or run
destructors when exceptions are thrown through them.

You cannot mix Java and C++ exceptions in the same translation unit.
It is believed to be safe to throw a C++ exception from one file
through another file compiled for the Java exception model, or vice
versa, but there may be bugs in this area.
 
V

Victor Bazarov

Steven said:
Steven T. Hatton wrote:
[snip...]
The two biggest objections I have to the current form of C++ exception
handling are:
[...]

Post this to comp.std.c++. Don't forget to read the answers.
 
S

Steven T. Hatton

Peter said:
Another way to say it would be:
"Something went wrong.
We won't tell you where or why.
- Lazy Programmers"

It's not always 'lazyness' that causes people to write bad code. They may
be inexperienced, and not fully understand how to use every aspect of the
language. You can say "that should never happen", but Stroustrup even says
you don't need to learn every detail of the language to use it.* This is
why I believe in requiring exceptions to be specified by any function that
may throw them, either directly or by functions they call. It's also why I
favor the automatic creation of an unknown exception that would be
initialize in a catch(unknown_exception ue){} block.

You can look at the timestamps of the messages in this thread to determine
how long it took me to convince myself that you really can't determine what
every exception is. I believe I now understand C++ exceptions to use them
effectively. If other people have half the problem I had in figuring them
out, it is likely there are a lot of C++ programmers who don't understand
exception handling.



* I'm finding there is a whole lot of the language you _do_ need to know in
order to use it well.
 
S

Steven T. Hatton

Victor said:
Steven said:
Steven T. Hatton wrote:
[snip...]
The two biggest objections I have to the current form of C++ exception
handling are:
[...]

Post this to comp.std.c++. Don't forget to read the answers.
I already did post something similar two day ago. I just posted the contents
of the message to which you referred as a follow up to my original post.
If you have good arguments against it, please present them in that context.

I posted about this a while back as well. The arguments against it
consisted of references to articles which were supposed to tell me why
checked exceptions were bad for C++. I was not convinced. The only
response I received that made sense what to allow both checked and
unchecked exceptions.
 
V

Victor Bazarov

Steven said:
Victor Bazarov wrote:

Steven said:
Steven T. Hatton wrote:
[snip...]
The two biggest objections I have to the current form of C++ exception
handling are:
[...]

Post this to comp.std.c++. Don't forget to read the answers.

I already did post something similar two day ago. I just posted the contents
of the message to which you referred as a follow up to my original post.
If you have good arguments against it, please present them in that context.

Good arguments against what? I throw and catch integers all the time.
Having everything I throw derive from std::exception is too much trouble
for me, I really couldn't care less whether it does have the 'what' member
or not. Also, my functions do not have exception specifications because
they are not necessarily the ones who throw. I use third-party libraries
(and not necessarily written for C++) all the time. I can't just stop and
tell them to begin rewriting them. It's simply not going to happen. But
it's not such a big deal to me or anybody else I know. The language gives
us freedom, and if you can't handle that freedom, what can I say to change
that? So, no, I am not going to present you with any arguments.
I posted about this a while back as well. The arguments against it
consisted of references to articles which were supposed to tell me why
checked exceptions were bad for C++. I was not convinced. The only
response I received that made sense what to allow both checked and
unchecked exceptions.

So, what's the point of your continuous arguing, then? You have convinced
yourself that only your point of view is correct, and no matter what you
hear in response it's not going to make sense, except if it follows your
own point of view. And please, don't bother replying, I know what you
would say: I am wrong of course.

V
 

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
474,174
Messages
2,570,940
Members
47,485
Latest member
Andrewayne909

Latest Threads

Top