C++ exception thrown inside constructor member initializer? - c++

Consider the following situation:
struct X { ... };
struct Y
{
Y(...);
...
X x;
...
}
X f()
{
...
if (...)
throw E;
...
}
Y::Y(...) :
... ,
x(f()) ,
...
{
...
}
Is there any undefined behaviour here? Are there any gotchas or potential problems with such a design when E is thrown?
Update:
Y::x may not be the only member variable of Y, may not be the first member variable in the class, and may be initialized half way through the Y::Y init list.

Is there any undefined behaviour here?
No. The construction of Y is aborted.
Are there any gotchas or potential problems with such a design when E is thrown?
No Y is ever created, so there is no destructor to call. Destructors for fully constructed elements, those declared before x in the class body, will be called automatically (how would you otherwise know how far the initialization list you were when it throw). If you need to destroy anything, then you must catch the exception and destroy it yourself. You cannot absorb the exception, you can rethrow it, throw a new exception, or do nothing which will result in the exception being rethrown anyway. For your particular use case, there shouldn't be anything to destroy since the constructor body is not going to be invoked at all.

When an exception is throwing during the construction of an object, the destructors of all fully constructed subobjects are called. That is, assuming your type X throwing an exception correctly cleans up any resources it may have allocated before the exception was thrown, there is no issue.

Related

Can we rethrow exception using constructor if yes then why?

class A
{
int a,b;
public:
A(int X,int Y)
{
X = a;
Y = b;
try
{
if (b == 0)
throw b;
else
cout << a / b;
}
catch (int a)
{
cout << a; //throw;can we rethrow??then what is purpose of it??
}
}
};
"can we rethrow?" - Yes. You can always rethrow a caught exception, to let someone higher up in the call-stack also handle it (or have it terminate the program if not caught).
An exception in the constructor means something really bad happened, and since constructors can't return a (invalid) value to indicate failure in proper object construction, there are 3 options: to initialize the object in some special state in a hope that somewhere else in the caller code it'll be checked and handled properly, or to set an external variable/flag to mark the initialization failure, or to throw an exception after releasing any memory that it dynamically allocated. In general, if an exception is thrown before an object is fully constructed, destructors will be called for any member objects that have been constructed so far. And if an array of objects has been partially constructed when an exception occurs, only the destructors for the array’s constructed objects will be called. In addition, destructors are called for every automatic object constructed in a try block before an exception that occurred in that block is caught.

Tell apart exceptions thrown from a function and from constructor or destructor of its argument

Suppose there is a function:
void f(X x);
and it is called like this:
f({});
(It is assumed that X has a suitable constructor.)
As I understand, expression f({}) will be compiled to something like this:
x is constructed
f is executed
x is destructed
Then how to tell apart exceptions thrown from f itself and exceptions thrown from constructor or destructor of x?
try {
f({});
} catch (...) {
// Where the current exception was thrown from?
}
Update. Suppose also that the implementations of f, X::X and X::~X cannot be changed and exceptions thrown from them are inherently indistinguishable.
Neither the C++ throw statement nor the standard exception constructors capture a stack trace. You cannot determine what threw from within a catch clause unless the thrown object conveys that information.
This could be done by either having X and f throw an object of a different type (and then you would have two or more catch clauses) or by having them fill an object with enough information to tell the errors apart (for instance, by overriding std::exception::what() to return something meaningful).
It's also possible to wrap the two in distinct catch clauses, but if the X object is passed by value, you still run the risk that the copy constructor or the move constructor throws (though in my experience move constructors rarely throw).

Try / Catch block substituted for a method block in a destructor

I was recently tasked with hunting down a memory leak in a part of our code. The leak ended up being in the destructor for a particular object...and I found something really strange. A former coworker wrote this:
File::~File()
try
{
Clear();
}
catch (...)
{
Log("caught exception");
}
The file class inherits from some base classes. My first question is: is this strictly legal C++? It compiles in Visual Studio 2008, but I showed it to a few friends / coworkers and they were fairly horrified that it worked.
It doesn't actually work as intended, though: the base class that this object inherits from has a destructor that is now never called (as opposed to if you just wrapped the destructor in a regular method block, having the try / catch as part of that method).
Can anyone take a stab at explaining why this is allowed, and why the base class destructor was not called? The destructor here was not throwing.
This is a function try block and it's completely legal.
See, for example, here.
The only time that you can do something in a function try block that you can't do in a normal try block in a function is catch exceptions thrown by expression in a constructor initializer list (and even then you end up having to throw something), but that doesn't apply here.
This GOTW #66 is particularly interesting, although it concentrates more on constructors. It contains this "moral":
Since destructors should never emit an exception, destructor function-try-blocks have no practical use at all.
Just to add clarification, the code as written will cause any exception caught to be rethrown due to ISO/IEC 14882:2003 15.3 [except.handle] / 16:
The exception being handled is rethrown if control reaches the end of a handler of the function-try-block of a constructor or destructor. [...]
However it is legal to have a parameterless return in the handler of a function try block for a destructor - it is only forbidden in a function try block for a constructor - and this will supress the rethrow of the exception. So either of these alternatives would prevent the exception from leaving the destructor.
File::~File()
try
{
Clear();
}
catch (...)
{
Log("caught exception");
return;
}
File::~File()
{
try
{
Clear();
}
catch (...)
{
Log("caught exception");
}
}
To answer the second part, "why the base class destructor was not called?", 12.4/6:
After executing the body of the
destructor and destroying any
automatic objects allocated within the
body, a destructor for class X calls
the destructors for X’s direct
members, the destructors for X’s
direct base classes...
A return statement (6.6.3) in a
destructor might not directly return
to the caller; before transferring
control to the caller, the destructors
for the members and bases are called.
This doesn't say that the member and base destructors are called if the destructor throws. However, 15.2/2 says:
An object that is partially
constructed or partially destroyed
will have destructors executed for all
of its fully constructed subobjects,
I think this should be true whether the object is "partially destroyed" because of an exception thrown from the body of the destructor, or because of an exception thrown from the the function try block of the destructor. I'm pretty sure that "after the body of the destructor" is supposed to mean also after a function try block.
Apparently Microsoft disagrees, though, and because of the function try block it hasn't generated "the body of the destructor", and hasn't done the things that happen after executing "the body of the destructor".
That doesn't sound right to me. GCC 4.3.4 does execute the base class destructor, whether the derived class dtor function try block throws or not. In the case where it throws, the base is destructed before the catch clause is executed.

How to Detect Stack Unwinding in a Destructor

I have a simple C++ object that I create at the start of function F() to ensure two matched functions (OpDo, OpUndo) are called at the start and return of the F(), by using the object's constructor and destructor. However, I don't want the operation to be undone in case an exception was thrown within the body of F(). Is this possible to do cleanly? I have read about std::uncaught-exception, but its use does not seem to be recommended.
Most people have used std::uncaught_exception() to try to tell if an exception is pending, so they can throw an exception from a destructor if there isn't one already. That is generally considered Not A Good Idea.
If you want to not undo an operation if an exception has thrown, it should do the trick.
Remember that the destructor is your last chance to release any resources an object has, because after the destructor ends the object does not exist, and any resources it held are now permanently leaked. If OpDo() allocates any memory or file handles or whatever, you do need to deal with that in the destructor no matter what.
You can subvert the Scope Guard idiom. Instead of not doing something in the destructor when no exception is thrown, we invert that and only do something if no exception is thrown:
class DoUndoRAII{
public:
DoUndoRAII()
: noexcept_(false)
{
// your stuff here
}
~DoUndoRAII(){
if(noexcept_){
// do whatever you need to do
}
}
void no_exception(){
noexcept_ = true;
}
private:
bool noexcept_;
};
void func(){
DoUndoRAII do_undo;
// last line
do_undo.no_exception();
}
When an exception is thrown, do_undo.no_exception() will never be called and thus never set the noexcept_ value to true. :) An example can be found here on Ideone.
Let's assume that your F returns some class Helper:
Helper F()
{
MyClass doUndoWrapper;
}
When flow is normal - Helper is created. When exception is raised no copy of Helper is created. Try use this semantic by placing to private region constructor of Helper and declaring F as friend - so no one could create helper.
class Helper
{
private:
friend Helper F();
Helper(){ //place there OpDo semantic - first entry
// construct this class
Helper(const Helper& copy){ //this must present to allow stack operations
// copy constructor will be called at end of `F` to return value
// so place OpUndo semantic there to mark success without exception

Exception slicing - is this due to generated copy constructor?

I've just fixed a very subtle bug in our code, caused by slicing of an exception, and I now want to make sure I understand exactly what was happening.
Here's our base exception class, a derived class, and relevant functions:
class Exception
{
public:
// construction
Exception(int code, const char* format="", ...);
virtual ~Exception(void);
<snip - get/set routines and print function>
protected:
private:
int mCode; // thrower sets this
char mMessage[Exception::MessageLen]; // thrower says this FIXME: use String
};
class Derived : public Exception {
public:
Derived (const char* throwerSays) : Exception(1, throwerSays) {};
};
void innercall {
<do stuff>
throw Derived("Bad things happened!");
}
void outercall {
try {
innercall();
}
catch(Exception& e)
{
printf("Exception seen here! %s %d\n", __FILE__, __LINE__);
throw e;
}
}
The bug was of course that outercall ends up throwing an Exception, instead of a Derived. My bug resulted from higher in the call stack attempts to catch the Derived failing.
Now, I just want to make sure I understand - I believe that at the 'throw e' line, a new Exception object is being created, using a default copy constructor. Is that what's really going on?
If so, am I allowed to lock out copy constructors for objects that will be thrown? I'd really prefer this not happen again, and our code has no reason to copy Exception objects (that I know of).
Please, no comments on the fact that we have our own exception hierarchy. That's a bit of old design that I'm working to correct (I'm making good progress. I've gotten rid of the home-grown string class, and many of the home-grown containers.)
UPDATE: To be clear, I had fixed the bug (by changing 'throw e' to 'throw') before I ever asked the question. I was just looking for confirmation of what was going on.
When you throw an object, you're actually throwing a copy of the object, not the original. Think about it - the original object is on the stack, but the stack is being unwound and invalidated.
I believe this is part of the standard, but I don't have a copy to reference.
The type of exception being thrown in the catch block is the base type of the catch, not the type of the object that was thrown. The way around this problem is to throw; rather than throw e; which will throw the original caught exception.
A quick google suggests that yes, you're throwing the copy constructor is required and must be public. (Which makes sense, as you're initializing a copy of e and throwing that.)
Anyway, just use throw without specifying the exception object, to rethrow what was caught in the catch. Shouldn't that solve the problem?
catch(Exception& e)
{
printf("Exception seen here! %s %d\n", __FILE__, __LINE__);
throw;
}
Yes.
throw e;
throws an exception of the static type of e, regardless of whatever e actually is. In this case, the Derived exception is copied to an Exception using a copy constructor.
In this case you can just
throw;
to get the Derived exception bubble up correctly.
If you're interesting in polymorphical throwing in some other cases, refer to the always so useful C++ FAQ Lite.
C++ never ceases to amaze me. I would have lost a lot of money had this been a bet on what was the behaviour!
The exception object is first copied to a temporary and you should have used throw. To quote the standard 15.1/3:
A throw-expression initializes a temporary object, called the exception object, the type of which is determined by removing any top-level cv-qualifiers from the static type of the operand of throw and adjusting the type from "array of T" or "function returning T" to "pointer to T" or "pointer to function returning T",respectively.
I think this gives rise to a very useful coding standard rule:
Base classes of an exception hierarchy should have a pure virtual destructor.
or
The copy constructor for a base class in an exception hierarchy shall be protected.
Either achieves the goal that the compiler will warn when you try to "throw e" since in the first case you cannot create an instance of an abstract class and the second because you cannot call the copy constructor.