Do method-scoped objects get destroyed when the method throws an exception? - c++

void MyClass::method()
{
SomeObject a;
methodThatCanThrowException();
}
I wish to catch exceptions higher up the call-stack, not in method() - but in this example will the SomeObject destructor be called or not?

Yes. That's why RAII works. It's why exceptions work. They wouldn't otherwise.
Full standard quote:
15.2 Constructors and destructors [except.ctor]
1. As control passes from a throw-expression to a handler, destructors are invoked for all automatic objects constructed since the try block was entered. The automatic objects are destroyed in the reverse order of the completion of their construction.
2. An object of any storage duration whose initialization or destruction is terminated by an exception will have destructors executed for all of its fully constructed subobjects (excluding the variant members of a union-like class), that is, for subobjects for which the principal constructor (12.6.2) has completed execution and the destructor has not yet begun execution. Similarly, if the non-delegating constructor for an object has completed execution and a delegating constructor for that object exits with an exception, the object’s destructor will be invoked. If the object was allocated in a new-expression, the matching deallocation function (3.7.4.2, 5.3.4, 12.5), if any, is called to free the storage occupied by the object.
3. The process of calling destructors for automatic objects constructed on the path from a try block to a throw-expression is called “stack unwinding.” If a destructor called during stack unwinding exits with an exception, std::terminate is called (15.5.1). [ Note: So destructors should generally catch exceptions and not let them propagate out of the destructor. —end note ]

Yes. It's sometimes called stack unwinding
Catching exceptions higher up the stack is often a good idea. I've seen lots of code that catches exception when it can't do much about it.
Just make sure SomeObject's destructor doesn't throw an exception.

Related

Why are the fields of the class automatic objects?

During my studing exeption's mechanism I found that there are calls of destructors for fields of the object while stack's unwinding. Let me explain explicitly:
class X
{
File_ptr aa;
Lock_ptr bb;
public:
X(const char* x,const char* y):aa(x),bb(y){}
//.......
}
So,now if Lock_ptr's constructor throws an exeption, object aa will be destroyed;
The question is "why"? I always thought that fileds of the object are not usual automatic (lochal) objects.They are created before constructor initializes them.So they can't be destryed after they're out of scope of constructor (Otherwise they would be destroyed as soon as constructor's finished its work)
Subobjects (including non-static data members) have the same storage duration as the complete objects to which they belong. This is not the same as saying that they are automatic. An automatic object is destroyed at the end of a block. A subobject is destroyed whenever its complete object is destroyed. For example, if the complete object is created with new and destroyed with delete (i.e. has dynamic storage duration), then the subobject is also created in the call to new, and destroyed in the call to delete. On the other hand, a subobject of an automatic object is also automatic.
If the constructor for X::bb throws an exception, then it means the complete object of type X cannot be constructed. All subobjects that have already been constructed, such as X::aa, must be destroyed, because a subobject, having the same storage duration as its complete object, cannot survive without the complete object.
On the other hand, if construction of the entire X object completes successfully, X::aa and other subobjects won't be destroyed until (shortly after) the complete X object is destroyed.
The construction and destruction rules for C++ are intended to guarantee that, as long as a program terminates normally, every object that is created is also destroyed exactly once. This is essential for the RAII idiom. In this example, if X::aa acquires resources when it is constructed, the language must ensure that those resources will be released. If X::aa's destructor is not called when construction of the X fails, then when should it be called?
X has a "real" constructor that constructs aa and bb, and then after that the constructor body of X is called. This is why the initializer list is before X's constructor "body". Inside of this "real" constructor, the bases and then members are created as if they were on the stack in the order they're declared in the class, including for stack unwinding. I even have a picture:
Destructors work on a vaguely similar principle, except in reverse, but can be even more complicated if the destructor is virtual. If the destructor is virtual, then there's three parts. There's a "stub" destructor that gets called when someone calls the destructor, which dispatches to the most-derived type's "real" destructor. The "real" destructor calls your destructor "body", and then destructs the members in the reverse order that they're declared in the class, and then it destructs the base classes (still in reverse order, same as a stack).
*QuestionC correctly observes that static members are completely independent of everything I wrote here.
Member objects (unless they are static) are constructed when the class constructor is called. The behavior you are seeing is normal and correct.
Member objects are not destroyed when the constructor is finished. They are destroyed when the class destructor is called (in reverse order of construction).

Are std::exception objects created when an exception is thrown?

I have a class CustomException, that implements std::exception, in which I explicitely deleted the copy and move constructors. When I throw an exception of that class, there are compiling errors for calling the deleted constructors.
Are CustomException instances being created somewhere? What objects are created when the exception is thrown?
When you throw, an exception object is constructed that has the same type as the operand of throw with top-level cv-qualifiers removed (if you throw an array or function, they also decay to their corresponding pointers).
So what you did is a no-go, I'm afraid.
C++ standard chapter [except.throw] §5:
When the thrown object is a class object, the copy/move constructor and the destructor shall be accessible, even if the copy/move operation is elided (12.8).
Before unwinding stack a throw operator (except throw; without an argument, used for rethrowing) creates an exception object in a special memory area. Depending on circumstances, the object is initialized in different ways: constructor, copy constructor, move constructor (https://en.cppreference.com/w/cpp/language/copy_elision) using what was provided to the throw operator. So the information is available from the exception object, which is alive until completing handling the exception, though what was provided to the throw operator is destroyed when the stack is unwound).
In your case the compiler needs the functions you deleted to either initialize the exception object when throwing the exception or to initialize the catch-clause argument, or both - since it is how the compiler does it by design (using the functions).

cleaning up after an exception [duplicate]

This question already has answers here:
Are destructors called after a throw in C++?
(3 answers)
Closed 9 years ago.
I have a code such as this:
class myclass
{
myclass()
{
// doing some init here
}
~myclass()
{
// doing some important clean up here
}
void Do()
{
// doing some work which may throw exception
}
}
and I am using this class in this way:
MyFunction()
{
myclass mc;
mc.do();
}
My question is :
If there is an exception in do function, what would happen? Is destructor of myclass called?
If no, what is the best way to handle this type of situations? Assume that I don't have the source code and I am sure about what is happening in destructor.
If there is an exception in do function, what would happen?
If you have any handler, it will be handled.
Is destructor of myclass called?
Yes, definitely. The standard quotes this::
An object of any storage duration whose initialization or destruction
is terminated by an exception will have destructors executed for all
of its fully constructed subobjects (excluding the variant members of
a union-like class), that is, for subobjects for which the principal
constructor (12.6.2) has completed execution and the destructor has
not yet begun execution. Similarly, if the non-delegating constructor
for an object has completed execution and a delegating constructor for
that object exits with an exception, the object’s destructor will be
invoked. If the object was allocated in a new-expression, the matching
deallocation function (3.7.4.2, 5.3.4, 12.5), if any, is called to
free the storage occupied by the object.
This whole process is known as "stack unwinding":
The process of calling destructors for automatic objects constructed
on the path from a try block to a throw-expression is called “stack
unwinding.” If a destructor called during stack unwinding exits with
an exception, std::terminate is called (15.5.1).
C++11 15.5.1 The std::terminate() function [except.terminate]
2 … In the situation where no matching handler is found, it is
implementation-defined whether or not the stack is unwound before
std::terminate() is called.
If the exception is caught somewhere, then stack unwinding will guarantee that the destructor is called for this object (and, in general, all automatic variables that go out of scope as a result of the exception). This is a very important guarantee, without which we could not use techniques like RAII to write exception-safe code.
If the exception is not caught, then the program will be terminated, and it's implementation-dependent whether or not the stack will be unwound first. If it's important to destroy the object cleanly even in that situation, then one option is to catch and rethrow the exception, outside the object's scope.
If the program is ended in some other way, e.g. by calling exit() or terminate(), or receiving an unhandled signal, then the stack won't be unwound. If you need clean destruction in these situations, then things will get messy.
C++ does not have explicit "finally" clauses like many other languages, but instead you rely in "RAII" which essentially is a technique of using scoped "automatic" variables and relying on the fact that their destructor will get called at the appropriate moment when they go out of scope.
In your case the destructor of myclass will be called even if mc.do() throws an exception. In a lot of these "closure" issues, the object you put at the top of the scope block is a class that is used only for the purpose of invoking the destructor on termination.
The "D" language comes with a special closure syntax. There have been attempts to write libraries that do that in C++ and with lambdas it is certainly easier to write than now than it used to be although I do not think they are a formal part of C++ as yet.

How does RAII work when a constructor throws an exception?

I am learning about the RAII idiom in C++, and how to use smart pointers.
In my reading, I have come across two things that, to me, seem to contradict each other.
Quoted from http://www.hackcraft.net/raii/:
...if a member object with RAII semantics has been created and an exception happens before the constructor has completed then its destructor will be called as part of the stack unwinding. Hence an object which controls multiple resources can guarnatee their cleanup even if it isn’t fully constructed by using member RAII objects.
But quoted from http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.10:
If a constructor throws an exception, the object's destructor is not run. If your object has already done something that needs to be undone (such as allocating some memory, opening a file, or locking a semaphore), this "stuff that needs to be undone" must be remembered by a data member inside the object.
And then the second linked source recommends using smart pointers to deal with the issue of things that were already allocated in the constructor.
So what actually happens in these scenarios?
You're misunderstanding the first quote. That's not hard, since it's confusing.
if a member object with RAII semantics has been created and an exception happens before the constructor has completed then its destructor will be called as part of the stack unwinding.
That's what it says. Here's what it meant:
if a member object with RAII semantics has been created and an exception happens in the outer object before the outer object's constructor has completed then the member object's destructor will be called as part of the stack unwinding.
See the difference? The idea is that the member object completed its constructor, but the owning type didn't. It threw somewhere in its constructor (or a constructor of another member that is initialized after that one). This will cause the destructor of all of its members to be called (all of the ones that completed construction, that is), but not its own destructor.
Here's an example:
class SomeType
{
InnerType val;
public:
SomeType() : val(...)
{
throw Exception;
}
};
When you create a SomeType instance, it will call InnerType::InnerType. As long as that doesn't throw, it will then enter SomeType's constructor. When that throws, it will cause val to be destroyed, thus calling InnerType::~InnerType.
There's no contradiction here; there's just some confusing terminology being used in different contexts.
If an object's constructor throws an exception, then the following occurs (assuming the exception is caught):
All local variables in the constructor have their destructors invoked, releasing all resources they've acquired (if any).
All of the direct subobjects of the object whose constructor threw an exception will have their destructors invoked, releasing resources they've acquired (if any).
All base classes of the object whose constructor threw will have their destructors invoked (since they were fully constructed before the derived class constructor ran)
Further cleanup from the caller etc. will take place.
As a result, any resources that are managed by smart pointers or other RAII objects that are data members of the object being destructed will indeed be cleaned up, but specialized code to do cleanup in the destructor of the object won't fire.
Hope this helps!
These two statements don't contradict each other, but the first one has some unfortunate language. When the construction of some object throws, it's deconstructor won't be called, but all objects owned by that object will be destructed by their individual deconstructors.
So with RAII and smart pointers the destructors for any pointer members of an object will be called independently of the destructor of the owing object. Raw pointers do not free the memory they point to and have to be deleted manually. Should the constructor of the owning object throw raw pointers will not be freed. This cannot happen with smart pointers.

Are destructors called after a throw in C++?

I ran a sample program and indeed destructors for stack-allocated objects are called, but is this guaranteed by the standard?
Yes, it is guaranteed (provided the exception is caught), down to the order in which the destructors are invoked:
C++11 15.2 Constructors and destructors [except.ctor]
1 As control passes from a throw-expression to a handler, destructors are invoked for all
automatic objects constructed since the try block was entered. The
automatic objects are destroyed in the reverse order of the completion
of their construction.
Furthermore, if the exception is thrown during object construction, the subobjects of the partially-constructed object are guaranteed to be correctly destroyed:
2 An object of any storage duration whose initialization or
destruction is terminated by an exception will have destructors
executed for all of its fully constructed subobjects (excluding the
variant members of a union-like class), that is, for subobjects for
which the principal constructor (12.6.2) has completed execution and
the destructor has not yet begun execution. Similarly, if the
non-delegating constructor for an object has completed execution and a
delegating constructor for that object exits with an exception, the
object’s destructor will be invoked. If the object was allocated in a
new-expression, the matching deallocation function (3.7.4.2, 5.3.4,
12.5), if any, is called to free the storage occupied by the object.
This whole process is known as "stack unwinding":
3 The process of calling destructors for automatic objects constructed
on the path from a try block to a throw-expression is called “stack
unwinding.” If a destructor called during stack unwinding exits with
an exception, std::terminate is called (15.5.1).
Stack unwinding forms the basis of the widely-used technique called Resource Acquisition Is Initialization (RAII).
Note that stack unwinding is not necessarily done if the exception is not caught. In this case it's up to the implementation whether stack unwinding is done. But whether stack unwinding is done or not, in this case you're guaranteed a final call to std::terminate.
C++11 15.5.1 The std::terminate() function [except.terminate]
2 … In the situation where no matching handler is found,
it is implementation-defined whether or not the stack is unwound before std::terminate() is called.
Yes, destructors are guaranteed to be called on stack unwinding, including unwinding due to exception being thrown. There are only few tricks with exceptions that you have to remember:
Destructor of the class is not called if exception is thrown in its constructor.
Exception is automatically re-thrown if caught in construction initialization list catch block.
If a throw is caught then normally cpp operations continue. This include destructors and stack popping. However if the exception is not caught, stack popping is not guaranteed.
Also a bare throw or empty throw cannot be caught by my mobile compiler.
example:
#include <Jav/report.h>
int main()
{
try { throw; }
catch(...) { rep("I bet this is not caught"); }
}