catch (...)

T

Tom Groszko

Given a try catch scenario

try
{ dosomething();
}
catch (...)
{ report some error
}

Is there any way to figure out what exception is being thrown and
represented by the ellipsis in the above code?
I am using MS C++ if that environment has something different.

I am catching an error and sure would like to know what is wrong. I have
tried to catch everything in the docs for the library and none of those are
the error.

Thanks
Tom G.
 
R

Ron Natalie

Tom Groszko said:
Is there any way to figure out what exception is being thrown and
represented by the ellipsis in the above code?
I am using MS C++ if that environment has something different.
Try it in the debugger. MS C++ has a side effect that catch ... will
(in certain cases) catch hardware exceptions (protection violations, etc...).
Even if it is a thrown C++ exception you can tell the debugger to stop on
the throw.
 
J

jeffc

Tom Groszko said:
Given a try catch scenario

try
{ dosomething();
}
catch (...)
{ report some error
}

Is there any way to figure out what exception is being thrown and
represented by the ellipsis in the above code?
I am using MS C++ if that environment has something different.

I am catching an error and sure would like to know what is wrong. I have
tried to catch everything in the docs for the library and none of those are
the error.

You either have to know the type you're catching, or test for the type
itself. For example, if you know you're getting an int, check the
documentation for what ints might be thrown. MS throws things like
CException, or something like that, so check the documentation and see
what's inside. Otherwise, you have to "filter":

catch(TypeA)
{}
catch(TypeB)
{}
catch(...)
{}
Looks a lot like a switch statement (the ... is "default").
 
T

Tom Groszko

I can stop in the catch block, but there is nothing to select and examine.
How do I tell the debugger to stop on a throw that I don't know where it is?
 
R

Ron Natalie

Tom Groszko said:
I can stop in the catch block, but there is nothing to select and examine.
How do I tell the debugger to stop on a throw that I don't know where it is?

Set a breakpoint before the try block somewhere. Run the app.
When you get to the breakpoint, go to the "Debug" menu and select
"Exceptions" .. scroll down to the end of the list to "Microsoft C++
Exceptions." Click on that and then on the "Stop Always" button.
Press OK. Continue the app. You'll get a break point where the
exception is thrown (it will be down in some function like CxxThrowException
so you'll have to look up the call stack to find the actual throw expression.
 
N

Nick Hounsome

jeffc said:
You either have to know the type you're catching, or test for the type
itself. For example, if you know you're getting an int, check the
documentation for what ints might be thrown. MS throws things like
CException, or something like that, so check the documentation and see
what's inside. Otherwise, you have to "filter":

catch(TypeA)
{}
catch(TypeB)
{}
catch(...)
{}
Looks a lot like a switch statement (the ... is "default").

A neat trick is to put all this in a common function:

try { doSomething(); } catch(...) { analyzeException(); }

....

void analyzeException()
{
try
{
throw; // rethrows caught exception
}
catch(A& a)
{
// diagnostics
throw;
}
catch(B& b)
{
// diagnostics
throw;
}
catch (...)
{
// diagnostics
throw;
}
}
 
J

jeffc

Nick Hounsome said:
A neat trick is to put all this in a common function:

try { doSomething(); } catch(...) { analyzeException(); }

...

void analyzeException()
{
try
{
throw; // rethrows caught exception
}

Yes, I do that trick myself. It's not intuitively obvious, but it does seem
to work well and it comes in handy for streamlining your code.
 
C

Cy Edmunds

Tom Groszko said:
Given a try catch scenario

try
{ dosomething();
}
catch (...)
{ report some error
}

Is there any way to figure out what exception is being thrown and
represented by the ellipsis in the above code?
I am using MS C++ if that environment has something different.

I am catching an error and sure would like to know what is wrong. I have
tried to catch everything in the docs for the library and none of those are
the error.

Thanks
Tom G.
[snip]

You could try this:

try
{
dosomething();
}
catch (std::exception &e)
{
std::cerr << "std::exception " << typeid(e).name() << '\n';
std::cerr << e.what() << '\n';
}
catch (...)
{
std::cerr << "non-standard exception\n";
}

If you don't know where the error is coming from but whoever threw it was
nice enough to base his exception class on std::exception you should be able
to get some information possibly including the actual type name and perhaps
an error message. OK, so that would be lucky. But if you were getting an
exception from MY code it would work. :)

catch(...) should be a last resort because once you are there you never know
what to do.

--
Cy
http://home.rochester.rr.com/cyhome/

PS depending on your compiler you might have to do something specific to
turn on RTTI.
 
N

Nick Hounsome

Cy Edmunds said:
Tom Groszko said:
Given a try catch scenario

try
{ dosomething();
}
catch (...)
{ report some error
}

Is there any way to figure out what exception is being thrown and
represented by the ellipsis in the above code?
I am using MS C++ if that environment has something different.

I am catching an error and sure would like to know what is wrong. I have
tried to catch everything in the docs for the library and none of those are
the error.

Thanks
Tom G.
[snip]

You could try this:

try
{
dosomething();
}
catch (std::exception &e)
{
std::cerr << "std::exception " << typeid(e).name() << '\n';
std::cerr << e.what() << '\n';
}
catch (...)
{
std::cerr << "non-standard exception\n";

That is a "non 'standard-exception'" i.e. the standard does not require or
even particularly encourage derivation from std::exception in user code.

Many well respected C++ authors seem to think that the std::exception
hierarchy if not std::exception itself are not teh greatest way to do
exceptions.
}

If you don't know where the error is coming from but whoever threw it was
nice enough to base his exception class on std::exception you should be able
to get some information possibly including the actual type name and perhaps
an error message. OK, so that would be lucky. But if you were getting an
exception from MY code it would work. :)

catch(...) should be a last resort because once you are there you never know
what to do.

This is not quite true - typically you should release resources allocated in
the try block and throw an exception of a type defined
by your method since your method has failed even if you don't know why. In
general you might not know how to recover but you do know how to clean up
and throw an exception.
You also know that it is a fault in your implementation not the calling
code.

It is a bit tedious but it is strictly speaking incorrect modelling to allow
ANY exception to propagate through your code unless you know its detailed
type because a caller does not know what to expect.
In an ideal world you would put a try block around anything that could throw
and convert all exceptions to a documented set defined for your method.
In a less than ideal world I would suggest that you do this whenever you
have declared some exceptions to throw or you use something that the client
does not know about (e.g. hidden use of networking producing network
exceptions is bad). For other cases you probably shouldn't use try blocks at
all - just use destructors to clean up.

P.S. When initially prototyping or where there are a small number of
possible exceptions I sometimes use the following cheap and cheerful
approach:

struct X
{
static const char E_BADSTUFF1[]; // a suitable string
static const char E_BADSTUFF2[];

void foo()
{
throw E_BADSTUFF1; // a bit lazy
}
void foo2()
{
throw "bad stuff 3"; // very lazy
}
};

This allows printing something useful and equality comparisons:

try
{
x.foo();
}
catch( const char* s )
{
cerr << "ERR: " << s << endl;
if( s == X::E_BADSTUFF1 )
...
}
 
R

Ron Natalie

jeffc said:
Yes, I do that trick myself. It's not intuitively obvious, but it does seem
to work well and it comes in handy for streamlining your code.
Bad suggestion with the OP's compiler. Rethrow is severely busted
in VC6.
 
J

jeffc

Ron Natalie said:
Bad suggestion with the OP's compiler. Rethrow is severely busted
in VC6.

Really? How so? I did it in VC, but I'm not sure if it was 5 or 6. I
actually did run into a problem. I wrote the same code, but I used a MFC
CString as a parameter to the exception class constructors I was using (the
CString had an error message.) This didn't work and I didn't know why - I
suspected you just couldn't use C++ that way, so I wrote Mr. Stroustrup an
email, and he said the "idiom" that Mr. Hounsome posted should work just
fine. It turns out there was a bug in CString (or exception handling) that
caused the destructor for the string to be called twice. But I doubt that's
what you're talking about, is it?
 
R

Ron Natalie

jeffc said:
. It turns out there was a bug in CString (or exception handling) that
caused the destructor for the string to be called twice. But I doubt that's
what you're talking about, is it?
It certainly is. The exception handler calls the destructor more than
once when rethrow is used. Not a problem if your classes have
trivial destructors, but if not ... BOOM
 
G

Gianni Mariani

Ron said:
Bad suggestion with the OP's compiler. Rethrow is severely busted
in VC6.

VC6 is broken in so many other ways ...

As far as comp.std.c++ goes, it seems like this is an appropriate idiom
and IMHO one thing that makes exceptions more palatable.
 
J

jeffc

Ron Natalie said:
It certainly is. The exception handler calls the destructor more than
once when rethrow is used. Not a problem if your classes have
trivial destructors, but if not ... BOOM

So it's any destructor, not just a CString problem. Ouch.
 
C

Cy Edmunds

Nick Hounsome said:
Cy Edmunds said:
Tom Groszko said:
Given a try catch scenario

try
{ dosomething();
}
catch (...)
{ report some error
}

Is there any way to figure out what exception is being thrown and
represented by the ellipsis in the above code?
I am using MS C++ if that environment has something different.

I am catching an error and sure would like to know what is wrong. I have
tried to catch everything in the docs for the library and none of
those
are
the error.

Thanks
Tom G.
[snip]

You could try this:

try
{
dosomething();
}
catch (std::exception &e)
{
std::cerr << "std::exception " << typeid(e).name() << '\n';
std::cerr << e.what() << '\n';
}
catch (...)
{
std::cerr << "non-standard exception\n";

That is a "non 'standard-exception'" i.e. the standard does not require or
even particularly encourage derivation from std::exception in user code.

The standard defines std::exception with a virtual what() function. I would
say that constitutes at least mild encouragement.
Many well respected C++ authors seem to think that the std::exception
hierarchy if not std::exception itself are not teh greatest way to do
exceptions.

My understanding is that Bjarne himself never liked the heirarchy. I don't
use it either. However, I always derive my exception classes from
std::exception. If everybody else also did the OP might not have such a
problem.

[snip]

I have no objections to your using char *'s for exceptions in your own code,
but if it ever has a chance of crossing my desktop I hope you will do
something better, preferably based on std::exception.
 
R

Ron Natalie

Cy Edmunds said:
The standard defines std::exception with a virtual what() function. I would
say that constitutes at least mild encouragement.

Note he said user code. The virtual what() function is essential for the other
standard exceptions derived from it to work. Doesn't say whether a user should
be definining his own or not.
My understanding is that Bjarne himself never liked the heirarchy. I don't
use it either.

And for good reason. In general, it's a bad idea in C++ to have "GOD" objects
that everything in the world derives from. C++ is not Smalltalk.

I have no objections to your using char *'s for exceptions in your own code,
but if it ever has a chance of crossing my desktop I hope you will do
something better, preferably based on std::exception.

The only downside to this I can think of is that if you have some code that
belongs to someone else between the throw and the handler. You might
specifically avoid using std::exception if you want to prevent someone from
randomly dinking with your exceptions up the call stack.
 
J

jeffc

Ron Natalie said:
And for good reason. In general, it's a bad idea in C++ to have "GOD" objects
that everything in the world derives from.

Why do you say that? I remember a CObject from VC++, although I didn't use
it.
 
M

Mike Smith

jeffc said:
Why do you say that? I remember a CObject from VC++, although I didn't use
it.

Because your god-object might not be the same as someone else's
god-object. Like, if you use someone else's library, where they define
their own god-object. Whose god-object do you use?
 
R

Ron Natalie

jeffc said:
Why do you say that? I remember a CObject from VC++, although I didn't use
it.

It should be noted that not even Microsoft derived everything from CObject.
CObject is part of the disgusting MFC package which is NOT a good example
of even how to do things in Windows. Fortunately, Microsoft got better in the
intervening years. GDI+ is more in line with sensible design, for example.

The first problem, if for no other reason is that the GOD object would need to
be polymorphic to be useful (and safe), which is not necessary for C++ objects
in general. Further, the conversion to this object wouldn't likely be any better
than void* which has problems of it's own. Best to have your hierarchies have
their own sensible roots.
 
J

jeffc

Ron Natalie said:
The first problem, if for no other reason is that the GOD object would need to
be polymorphic to be useful (and safe), which is not necessary for C++ objects
in general. Further, the conversion to this object wouldn't likely be any better
than void* which has problems of it's own. Best to have your hierarchies have
their own sensible roots.

I guess I would have thought about it more as a design problem - for
example, you'd know if you were going to be using polymorphism as a
requirement in your design for all objects. If not, you wouldn't do it. I
didn't know if there was a more technical reason it was a Really Bad Idea in
C++. Obviously, an Object-based hierarchy makes a lot more sense for an
environment like Smalltalk.
 

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,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top