Is it possible to handle exceptions in these scenarios:
thrown from constructor before entering main()
thrown from destructor after leaving main()
You can wrap up your constructor withing a try-catch inside of it.
No, you should never allow exception throwing in a destructor.
The funny less-known feature of how to embed try-catch in a constructor:
object::object( int param )
try
: optional( initialization )
{
// ...
}
catch(...)
{
// ...
}
Yes, this is valid C++. The added benefit here is the fact that the try will catch exceptions thrown by the constructors of the data members of the class, even if they're not mentioned in the ctor initializer or there is no ctor initializer:
struct Throws {
int answer;
Throws() : answer(((throw std::runtime_error("whoosh!")), 42)) {}
};
struct Contains {
Throws baseball;
Contains() try {} catch (std::exception& e) { std::cerr << e.what() << '\n'; }
};
Yes: don't use dangerous global objects!
It might be possible to set an exception handler before construction / destruction of the objects in question, that one should be able to handle those exceptions.
For constructors, there's some weird new syntax that allows exceptions to be caught within the constructor. Not sure how that works, and it's not commonly implemented in many compilers.
For destructors, you have to wrap the content of the destructor in a try { code(); } catch(...) {} block. Which may not always be the desired behavior, depending on what you want to achieve in that destructor.
Short answer: no.
Any global object that throws an exception in its constructor will cause an unhandled exception (that is, terminate be called).
Any class that throws an exception in its destructor is a broken class.
Using the singleton pattern rather than globals will give you more options.
Related
This is a follow-up question of the post. Please see the end of this question for a definition of "function try block".
Question: If a function try block does not "handle" the exception raised in the constructor, why do we need them after all? Could you give an example taking advantage of function try block?
Considering the following code.
#include <iostream>
#include <new>
#include <exception>
using namespace std;
struct X {
int *p;
X() try : p(new int[10000000000]) {}
catch (bad_alloc &e) {
cerr << "exception caught in the constructor: " << e.what() << endl;
}
};
int main() {
try {
X x;
}
catch (exception &e){
cerr << "exception caught outside the constructor: " << e.what() << endl;
}
return 0;
}
The output is
exception caught in the constructor: std::bad_alloc
exception caught outside the constructor: std::bad_alloc
It seems to me that, no matter what I do in the function try block, the exception is always going to be thrown to the outer scope which calls the constructor, e.g. the X x; in the above code.
Definition of "function try block", excerpted from "C++ Primer 5th."
To handle an exception from a constructor initializer, we must write the constructor as a function try block. A function try block lets us associate a group of catch clauses with the initialization phase of a constructor (or the destruction phase of a destructor) as well as with the constructor’s (or destructor’s) function body.
You're right that the exception is always propagated.
The function try block enables you to catch that exception and e.g. destroy an object passed as argument (maybe this is a smart pointer class?), without introducing an artificial base class.
More generally, it gives you the ability to clean up state changes introduced by the call of the function.
For the case of a constructor:
With the exception propagation destructors are called for all successfully constructed sub-objects, including base class sub-objects (if any).
However, this not completely constructed object's own destructor is not called. The function try block is ideally not a device for doing things that would go in that destructor. The not-completely-created object's own destructor has nothing to do, for its task is to clean up state changes introduced by the constructor body and/or later member function calls, and with a common "rule of zero" design there's no such as yet.
When a constructor throws, the corresponding destructor doesn't run. That's the reason for the quote in your book : cleanup has to be done by the constructor itself.
But your example shows that the exception propagates. This is necessary since the constructor failed, and therefore no object was created. The calling code should not proceed as if the constructor created an object.
I have the following code where a variable is being initialized with the result of a function call. This function throws so I set up a try-catch to catch the exception. For some reason the exception is still showing up on the screen even after the catch clause runs.
#include <iostream>
#include <stdexcept>
int f() { throw std::invalid_argument("threw"); return 50; }
struct S
{
S()
try : r(f())
{
std::cout << "works";
}
catch(const std::invalid_argument&)
{
std::cout << "fails";
}
int r;
};
int main()
{
S s;
}
This code prints "fails" after showing the exception:
terminate called after throwing an instance of 'std::invalid_argument'
what(): threw
Why is the exception still thrown? I have the same code set up in main and it works without fail:
int main()
{
try { throw std::invalid_argument("blah"); }
catch(const std::invalid_argument&) { }
}
So why does it fail when being used in an initializer list?
Constructors with function try blocks (like what you have for S) automatically rethrow any exceptions caught by the catch block. Consequently, after the catch catches the exception, it rethrows it. This behavior is different from normal catch handlers, which don't do this. I think the rationale is that if construction of a data member or base class fails, the object has failed to construct. The purpose of the catch handler is just to do any extra cleanup before the exception propagates outward.
Hope this helps!
From the C++11 Standard, 15.3/15:
The currently handled exception is rethrown if control reaches the end of a handler of the function-try-block
of a constructor or destructor.
The reasons are well explained in the GOTW Jerry links under your question, but summarily: imagine if it hadn't rethrown, then the next lines after S s; will presumably attempt to use s despite it never having completed construction, and when s leaves scope the constructor will have arranged a call to the destructor for s - potentially freeing never-initialised pointers, releasing never-taken locks etc..
By way of contrast, if you let the data member be default initialised then assign to it from a try/catch block in the constructor body, the state of the object including bases and data members can potentially be kept in some coherent state: it's up to you as the programmer to decide whether that state's ok - i.e. whether you'll use the try/catch block inside the constructor body, and have later member functions handle a potentially default-constructed data member.
I have a class that can throw an exception in its constructor. How can I declare an instance of that class in a try/catch block, while still making it available in the right scope?
try { MyClass lMyObject; }
catch (const std::exception& e) { /* Handle constructor exception */ }
lMyObject.DoSomething(); // lMyObject not in scope!
Is there an alternative way to accomplish this, while respecting the RAII idiom?
I'd prefer not to use an init() method for two-phased construction. The only other thing I could come up with was:
MyClass* lMyObject;
try { lMyObject = new MyClass(); }
catch (const std::exception& e) { /* Handle constructor exception */ }
std::shared_ptr<MyClass> lMyObjectPtr(lMyObject);
lMyObjectPtr->DoSomething();
Works OK, but I'm not happy with the raw pointer in scope and pointer indirection. Is this just another C++ wart?
If a constructor throws that means the object failed to initialize and hence it failed to start its existence.
MyClass* lMyObject;
try { lMyObject = new MyClass(); }
catch (std::exception e) { /* Handle constructor exception */ }
In the above if the constructor throws an exception, lMyObject is left uninitialized, in other words, the pointer contains an indeterminate value.
See classic Constructor Failures for a detailed explanation:
We might summarize the C++ constructor model as follows:
Either:
(a) The constructor returns normally by reaching its end or a return statement, and the object exists.
Or:
(b) The constructor exits by emitting an exception, and the object not only does not now exist, but never existed.
There are no other possibilities.
The best way of writing your code is this:-
MyClass lMyObject;
lMyObject.DoSomething();
No trys, catches, or pointers.
If the constructor throws, then DoSomething can't get called. Which is right: If the constructor threw, then object was never constructed.
And, importantly, don't catch (or even catch/rethrow) exceptions unless you have something constructive to do with them. Let exceptions do their job and ripple up until something that knows how to handle them can do its job.
Constructors are for putting an object into a consistent state and establishing class invariants. Allowing an exception to escape a constructor means that something in that constructor has failed to complete, so now the object is in some unknown weird state (which may include resource leaks now too). Since the object's constructor has not completed, the compiler will not cause it's destructor to be invoked either. Perhaps what you're looking for is to catch the exception inside the constructor. Assuming it's not rethrown, this would cause the constructor to complete execution, and the object is now fully-formed.
You don't need to use shared_ptr, use unique_ptr:
std::unique_ptr<MyClass> pMyObject;
try { pMyObject.reset(new MyClass()); }
catch (std::exception &e) { /* Handle constructor exception */ throw; }
MyClass &lMyObject = *pMyObject;
lMyObject.DoSomething();
Obviously, it's your responsibility to ensure that the program does not fall through the catch block without either initialising pMyObject, or exiting the function (e.g. via return or throw).
If available, you can use Boost.Optional to avoid using heap memory:
boost::optional<MyClass> oMyObject;
try { oMyObject.reset(MyClass()); }
catch (std::exception &e) { /* Handle constructor exception */ throw; }
MyClass &lMyObject = *oMyObject;
lMyObject.DoSomething();
You could set up MyClass's copy constructor to accept garbage input, thereby effectively declaring a pointer with your declaration of the object. Then you could manually call the default constructor within the try block:
MyClass lMyObject(null); // calls copy constructor
try {
new (lMyObject) MyClass(); // calls normal constructor
}
catch (const std::exception& e) { /* Handle constructor exception */ }
lMyObject.DoSomething();
I have an exception class:
class MyException : public std::exception
{
public:
MyException( char* message )
: message_( message )
{
if( !message_ ) throw std::invalid_argument("message param must not be null");
}
};
And at my throw site:
try {
throw MyException( NULL );
}
catch( std::exception const& e ) {
std::cout << e.what();
}
(code was not compiled, so please excuse any errors)
I'm wondering what will happen when I throw from a constructor while constructing due to another throw. I assume this is legal, and the catch will end up catching a std::invalid_argument, and the previous exception thrown (MyException) will be ignored or cancelled out.
My goal with this design is to enforce invariants in my exception class. message_ should never be NULL, and I don't want to have if conditions to check if it is null in my what() overload, so I check them in the constructor and throw if they are invalid.
Is this correct, or is the behavior different?
The object you intend to throw (in this case MyException) must be successfully constructed before it can be thrown. So you're not throwing it yet, since it hasn't been constructed.
So this will work, throwing the exception from within MyException's constructor. You won't trigger the "throwing an exception while handling an exception causes std::terminate" issue.
15.1 Throwing an exception n3376
Paragraph 7
If the exception handling mechanism, after completing evaluation of the expression to be thrown but before the exception is caught, calls a function that exits via an exception, std::terminate is called (15.5.1).
This means that until the constructor (of the object being thrown in this case) completes nothing special is going to happen. But after the constructor completes any other uncought exception will result in terminate() being called.
The standard goes on to provide an example:
struct C
{
C() { }
C(const C&) { throw 0; }
};
int main()
{
try
{
throw C(); // calls std::terminate()
}
catch(C) { }
}
Here terminate is called because the object is first created. But then the copy construction is called to copy the exception to the holding location (15.1.4). During this function call (copy construction) an uncaught exception is generated and thus terminate is called.
So your code as shown should work as expected.
Either: A MyException is generated with a good message and thrown
Or: A std::invalid_argument is generated and thrown
If you want to check invariants that should always be true, you should use assertions. Exceptions are meant for unusual situations that are expected to happen, like corner cases or bad user input.
If you use exceptions to report bugs in your code, you could accidentally hide them with catch(...). This is especially important if you are writing library code, because then you never know if other people might catch and ignore the exception, even if it means that the system has reached an invalid state.
Another advantage of assertions is that you can completely disable them if you want, such that they will no longer incur any performance penalties. This allows you to be really paranoid with those checks in your debug builds and still have a lightning fast release build.
Please have a look at demo code :
class myError
{
const char* str;
public:
myError():str(NULL) {}
myError(const char* temp)
{
str = temp;
}
const char* what()
{
return str;
}
};
class ab
{
int x;
public:
ab() try :x(0)
{
throw myError("error occured in the constructor of class ab");
}
catch(myError& temp)
{
std::cout<<"Handler no. 1 of ab constructor"<<std::endl;
}
};
int main () try
{
ab bb;
cout << "Resumed execution!" << endl;
return 0;
}
catch(myError& temp)
{
std::cout<<"Handler below the main function"<<std::endl;
std::cout<<"And the error is :" <<temp.what();
}
My Questions :
Why only function try block's handler of ctor and dtor only rethows the exception? ,
and when you simply throw exception inside ctor , its handler doesn't rethrows the object? i.e
Ctor::Ctor()
{
try{
throw Excep1();
}
catch(Excep1& temp) {
std::cout<<"Doesn't rethrows the exception object";
}
}
I wanna know that how to resume the control back to cout << "Resumed execution!" << endl; , after handling rethrown object?
why is it often said that we shouldn't place function try block on dtor of base class?
The usual rule is that a catch block doesn't rethrow unless you ask it
to. How would you stop the exception from propagating otherwise. In
the case of a constructor, however, if something in the initialization
list throws, then you haven't got a fully constructed object; there is
nothing you could do with the object, not even call the destructor on
it. And if the function catch block of the constructor doesn't
rethrow, what is it going to do, since it cannot simply return (and
leave the variable on the stack)?
In all other cases, it's up do the function containing the catch block
to know what to do. In the case of your main, for example, you could
write:
try {
ab bb;
} catch (...) {
}
std::cout << "Resumed execution!" << std::endl;
What you can't do is execute code where bb would be in scope and
accessible, but not have been correctly constructed.
As for why you shouldn't place a function try block on the destructor of a
base class, I've never heard that rule. In general, destructors
shouldn't throw, so there's no point in wrapping them in a try block,
period.
For the second question, destructors shouldn't be throwing period. Consider a case where your destructor is freeing a lot of memory through delete. What would happen if your destructor threw an error before finishing the clean up? You now have a memory leak. If your destructor is causing a runtime error, then you probably have problems elsewhere in your code that you need to fix.
As usually, Herb Sutter knows and explains everything:
If the handler body contained the statement "throw;" then the catch block would obviously rethrow whatever exception A::A() or B::B() had emitted. What's less obvious, but clearly stated in the standard, is that if the catch block does not throw (either rethrow the original exception, or throw something new), and control reaches the end of the catch block of a constructor or destructor, then the original exception is automatically rethrown.
More in his article