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).
Related
in C++, when the object's desctructor is called, it first invokes child class's destructor, and then parent's, which is the opposite of construct procedure.
But why? It seems to be a simple question, but I haven't found a satisfying answer on the internet. Could someone explain the nessisity of doing destructing in such sequence?
Since this was tagged [language-lawyer], this is the rule that says what a destructor does:
[class.dtor]
After executing the body of the destructor and destroying any objects with automatic storage duration allocated within the body, a destructor for class X calls the destructors for X's direct non-variant non-static data members, the destructors for X's non-virtual direct base classes and, if X is the most derived class ([class.base.init]), its destructor calls the destructors for X's virtual base classes.
All destructors are called as if they were referenced with a qualified name, that is, ignoring any possible virtual overriding destructors in more derived classes.
Bases and members are destroyed in the reverse order of the completion of their constructor (see [class.base.init]).
Why?... It just makes sense. Things that are constructed in one order are generally destroyed in the opposite order. This convention applies to sub objects of classes, as well as elements of arrays, local variables in a function as well as objects with static storage duration destroyed at the end of the program. I cannot think of anything where this isn't the case.
Although dependencies between objects within their lifetime can be two-directional, during the construction and destruction the dependency can only be in one direction. Object that is created before cannot depend - within its constructor - on an object that is created later (because that object doesn't exist yet). Same applies to destruction but in reverse: An object that is destroyed later cannot depend - within its destructor - on an object destroyed before (because that object doesn't exist anymore).
If you can depend on something within your construction, then you will typically expect to be able to depend on that something within the destruction. In other words, you would expect the direction of dependency to remain in the same direction. The inverse destruction order satisfies this expectation.
To return to the c/d-tors, constructor body is the last thing to execute in the constructor, so the destructor body should be the first thing to execute in the destructor. And it will be useful in some cases to be able to use the base sub object within destructor body, which wouldn't be possible if it had already been destroyed.
Why does the base object need to exsit in a valid state in destructing procedure?
To understand this, it should help to think about why the destructor body exists in the first place. Typically, it is to change the internal state of the class in preparation for ending the lifetime. A typically familiar action is deletion of an owning pointer stored as a member (this is just an example: use smart pointers instead). If the object no longer exists in a valid state, then it would be too late to touch that now-invalid state.
but any base class function could be virtual function, which could also access child member in destructor procedure.
Virtual function calls resolve to the current class during destruction (just like during construction).
Assuming you're talking about parent/child meaning inheritance consider that
struct Car : Vehicle { ... };
is not really much different than
struct Car { Vehicle _base; ... };
except that automatically when you refer to a Vehicle property in a Car method _base. is implicitly added by the compiler.
The standard even calls this the "base class sub-object"... it's an object that has no name and that you use implicitly, but it's still there.
Now in C++ members of a class are constructed before the class itself, and destroyed after. The same happens to the implicit "base class sub-object". So when building a car you need first to build the vehicle... and after destroying the car all individual members are destroyed, including the vehicle.
Another question cites the C++ standard:
3.8/1 "The lifetime of an object of type T ends when: — if T is a class type with a non-trivial destructor (12.4), the destructor call
starts, or — the storage which the object occupies is reused or
released."
It would seem that this means accessing members of an object from a destructor is not allowed. However this seems to be wrong, and the truth is something more like what's explained in Kerrek SB's answer:
Member objects come alive before a constructor body runs, and they
stay alive until after the destructor finishes. Therefore, you can
refer to member objects in the constructor and the destructor.
The object itself doesn't come alive until after its own constructor
finishes, and it dies as soon as its destructor starts execution. But
that's only as far as the outside world is concerned. Constructors and
destructors may still refer to member objects.
I'm wondering if in the destructor I can pass the object's address to an outside class, like:
struct Person;
struct Organizer
{
static void removeFromGuestList(const Person& person); // This then accesses Person members
}
struct Person
{
~Person() {
// I'm about to die, I won't make it to the party
Organizer::removeFromGuestList(*this);
}
};
This seems OK to me as I think an object's lifetime lasts until after the destructor finishes, however this part of the above answer has me doubting:
The object itself doesn't come alive until after its own constructor
finishes, and it dies as soon as its destructor starts execution. But
that's only as far as the outside world is concerned. Constructors and
destructors may still refer to member objects.
The C++ Standard does seem to be just a little bit self-contradictory regarding the exact status of class members during execution of the destructor.
However, the following excerpt from this Draft C++ Standard may give some reassurance that your call to the removeFromGuestList function should be safe (bold italics formatting added by me):
15.7 Construction and destruction
1 For an object with a non-trivial constructor, referring to any non-static member or base
class of the object before the constructor begins execution results in
undefined behavior. For an object with a non-trivial destructor,
referring to any non-static member or base class of the object after
the destructor finishes execution results in undefined behavior.
What remains unclear (at least, to me) is whether or not referring to those class members via a reference to the object being destroyed is valid once the destructor has started execution. That is, assuming your Person class has a member, ObjectType a, is referring to person.a in your removeFromGuestList function valid?
On the other hand, rather than passing *this as its argument, if you were to pass each required member as a 'distinct object', then you would be safe; so, redefining that function as, say, removeFromGuestList(const ObjectType& a) (with possible additional arguments) would be completely safe.
Is there a way to make a destructor of a class NOT call the destructor of one of the class members and/or NOT call the destructor of its base class?
In case this is not possible, is creating certain class members with placement-new and destructing (/not-destructing) them manually a possible workaround? Thanks!
EDIT:
The reason I need this: Class C owns object M. M has a non-trivial destructor. C is friend of M and manages M in a way that there is no need to call M's destructor. It is OK to call it but it means performance overhead. (it's a problem in this case.)
I was thinking to make an a derived class from M that has a destructor that does nothing, but then that would still call the destructor of the base.
At construction time, C++ ensures that the subclasses contructors are first called, then the members are contructed, and finally the appropriate constructor is applied. At destruction time the symetric is done.
That means that you cannot prevent the application of a base class destructor, nor of any member constructor, as soon as the object is destructed. If you want to only destruct some, you must find a way to not destruct the object (just use a raw pointer...) and manually call destructors on what you want. But you certainly do not want to do that!
C++ is very confident on the programmer skills, so it is easy to write a program invoking undefined behaviour. If you find yourself trying to subvert the C++ compiler to not call the destructor of a base class or of a member, you have a major problem. The member you do not want to destroy should not be a member but more probably a pointer (raw or shared) or a reference to an external object that will have its own lifetime management. And the base class should probably also be a pointer or reference to an external object, and here again the lifetime can (and should) be managed outside of the class.
If the destructor has observable side-effects, then it would be undefined behaviour to end the lifetime of the object without invoking the destructor. This is covered in C++14 [basic.life]/4:
A program may end the lifetime of any object by reusing the storage which the object occupies or by explicitly calling the destructor for an object of a class type with a non-trivial destructor. For an object of a class type with a non-trivial destructor, the program is not required to call the destructor explicitly before the storage which the object occupies is reused or released; however, if there is no explicit call to the destructor or if a delete-expression is not used to release the storage, the destructor shall not be implicitly called and any program that depends on the side effects produced by the destructor has undefined behavior.
So, there is no way to get around it. Perhaps you could redesign your code so that the destructor doesn't execute any unnecessary statements, or something.
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.
I don't understand this:
3.8/1 "The lifetime of an object of type T ends when: — if T is a class type with a non-trivial destructor (12.4), the destructor call
starts, or — the storage which the object occupies is reused or
released."
If the lifetime ends before the destructor starts, doesn't that mean accessing members in the destructor is undefined behavior?
I saw this quote too:
12.7 "For an object with a non-trivial destructor, referring to any non-static member or base class of the object after the destructor
finishes execution results in undefined behavior."
But it doesn't make clear what's allowed during the destructor.
If the lifetime ends before the destructor starts, doesn't that mean accessing members in the destructor is undefined behavior?
Hopefully not:
From N3242 Construction and destruction [class.cdtor] /3
To form a pointer to (or access the value of) a direct non-static member of an object obj, the construction of obj shall have started and its destruction shall not have completed, otherwise the computation of the pointer value (or accessing the member value) results in undefined behavior.
The "lifetime" of an object is relevant for consumers of the object, not the object itself. Therefore a consuming class should not attempt to access members of an object once destruction has started.
No, there's no problem:
Member objects come alive before a constructor body runs, and they stay alive until after the destructor finishes. Therefore, you can refer to member objects in the constructor and the destructor.
The object itself doesn't come alive until after its own constructor finishes, and it dies as soon as its destructor starts execution. But that's only as far as the outside world is concerned. Constructors and destructors may still refer to member objects.
"Lifetime" doesn't mean that. It is a precisely defined term in the standard that has a variety of implications, but it might not have all the implications that you would think. Members can still be used during construction and destruction, outside code can call member functions, etc, etc.
Granted, it's a bit odd for client code to call member functions concurrently with the destructor, but not unheard of and certainly not disallowed by the language. In particular, std::condition_variable explicitly allows the destructor to be invoked while there are outstanding calls to condition_variable::wait(). It only prohibits new calls to wait() after the destructor starts.