throw from c'tor

A

Alf P. Steinbach

* Clark S. Cox III:
Not if you rethrow it.

Depends what "hide a bug" means. If a debugger or the program's run
time library catches an uncaught exception and reports its origin, then
the origin might be reported as the last rethrow site instead of the
original site, with the original throw's program state lost. Another
example is that a certain popular compiler has historically defaulted to
using a language extension where catch(...) catches non-C++ exceptions
that typically signal a botched program state (e.g. division by zero,
nullpointer dereferencing, stack overflow), in that state cleanup code
in such a catch(...) may indeed hide the bug completely, whereas without
the catch(...) one would have an uncaught non-C++ exception.

For only standard C++, without practical considerations such as those
above, I'm not sure whether catch(...) with rethrow can hide a bug. One
vague argument that it probably can't is that the device is used
extensively in one of the most popular implementations of the standard
library. One vague argument that it can is that as I recall that usage
has been criticized, but I don't recall exactly what the critique was.

Generally it's better to use RAII -- cleaning up via destructors --
than catch(...). One exception is where general exception translation
based on a nested rethrow-and-catch is employed: that can't be easily
expressed without catch(...). Another exception is at the top level of
a program or thread, assuming that the end-user doesn't have a debugger.
 
V

VJ

Clark said:
VJ said:
Kai-Uwe Bux said:
You are missing the point. Consider the templated variation:

template < typename T >
struct X {
T * a;
T * b;
std::size_t l;
X ( std::size_t n )
: a ( 0 )
, b ( 0 )
, l ( n )
{
try{
a = new T [l];
b = new T [l];
}
catch( ... ) {
delete a;
delete b;
throw;
}
}
};

Within the constructor, you have no chance of knowing what causes the
exception (you might guess it's bad_alloc, but it could be the
constructor
of T just as well). Also, the constructor of X does not really want to
know. All it can do is clean up the mess it did during construction,
i.e.,
deallocate the members a and b. For that purpose, it does not need to
know why construction of these arrays failed. Thus, the catch(...) in the
constructor of X is justified.

In this specific code - I see only std::bad_alloc could be thrown


Really? What if MyConcreteType is defined like so:

struct MyConcreteType
{
MyConcreteType() { throw 42; }
};

It is if you want to throw specific exception. For example


class S
{
public:
class P{};

S()
{
throw P();
}
};






In this example no, but there might be a function called in the ctor,
which throws another exception. If you catch that exception, who knows
what you can break in you program,


Tell me one thing that could be broken by this use of "catch(...)".


Lets say for example you want to throw 42 when a file you want to open
is missing. If you catch this throw like this, you will have no idea
what went wrong, and other parts of your program will behave strangely.
On the other hand, if you do not catch it, your program will crash but
you will get a message why (unhandled exception).
Off course that exception should get caught somewhere else:


try
{
X< MyConcreteType > inst1;
}
catch( int &number)
{
if ( 42 == number )
{
cout<<"missing file"<<endl;
}
}

BTW I wouldnt throw numbers like that
 
V

VJ

Kai-Uwe Bux said:
VJ wrote:

Kai-Uwe Bux said:
You are missing the point. Consider the templated variation:

template < typename T >
struct X {
T * a;
T * b;
std::size_t l;
X ( std::size_t n )
: a ( 0 )
, b ( 0 )
, l ( n )
{
try{
a = new T [l];
b = new T [l];
}
catch( ... ) {
delete a;
delete b;
throw;
}
}
};
True: in a different code in the try-block, catch(...) could be bad. Note
that nobody in this thread says that catch(...) is always or even generally
a good idea. We are talking about very specific code.

Ok, in that case I agree :)

This class is ok, cause you rethrow
 
C

Clark S. Cox III

VJ said:
Lets say for example you want to throw 42 when a file you want to open
is missing. If you catch this throw like this, you will have no idea
what went wrong, and other parts of your program will behave strangely.

No, they won't, as the exception was re-thrown. Other code will still
have to catch the exception themselves. I am beginning to sense that you
do not understand what a throw statement without a parameter does. Try
running the following, and you will see that even with the catch(...),
no information is lost, nor is there any trouble discerning what went wrong.

#include <iostream>
using namespace std;

void foo()
{
try
{
throw 42;
}
catch(...)
{
cout << "Caught some exception, re-throwing\n";
/* This throw will re-throw whatever was caught */
throw;
}
}

int main()
{
try
{
foo();
}
catch(int i)
{
cout << "Caught: " << i << endl;
}
return 0;
}

On the other hand, if you do not catch it, your program will crash but
you will get a message why (unhandled exception).
Off course that exception should get caught somewhere else:

try
{
X< MyConcreteType > inst1;
}
catch( int &number)
{
if ( 42 == number )
{
cout<<"missing file"<<endl;
}
}

Yes, but for this to not leak, the catch(...) block is needed inside X's
constructor.
BTW I wouldnt throw numbers like that

Nor would I, but generic code has to be prepared for it.
 

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,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top