Class destructor memory handling in C++ - c++

What potential memory leaks won't an implicit destructor handle? I know that if you have anything stored on the heap it won't handle it, and if you have a connection to a file or a database, that needs to be handled manually. Is there anything else? What about, say, non-base data types like vectors?
Also, in an explicit destructor, need you destroy non-heap variables which would have been destroyed by the implicit, or are they handled automatically?
Thanks

vectors and the like will deallocate themselves because their destructor is called.
In fact your problem will lie with anything that would cause a problem of a dangling pointer (or handle or whatever), ie anything that needs to be manually Closed or de-allocated won't be in an implicit destructor. Anything that destructs itself properly will be fine. This is why the RAII idiom is so popular :)

I think the question is upside-down. Don't think in terms of what object destruction doesn't do: think in terms of what it does do.
If a class only has an implicit destructor, then when it is destroyed, all non-static data members are destroyed too, as are all base-class sub-objects.
You can argue a bit whether this is done "by the implicit destructor" or not - if you write a destructor, those things still happen. It's part of the object destruction process itself, rather than part of the code of the destructor as such.
So, if your "connection to a file" is a FILE* class member, then the default destructor doesn't release it, because FILE* is a C thing, and it doesn't have a destructor. Destroying a FILE* does nothing. If your "connection to a file" is a std::ofstream, then it does have a destructor, and the destructor tries to flush and close the connection.
Vector has a destructor which release the vector's resources. This means that in turn the elements in the vector have their destructors called.
For each member variable you have, you should look at the corresponding documentation to see how resources are handled for that type. Obviously with experience, you start to remember the answers.
If the member variable is a pointer, then the implicit destructor doesn't do anything with it. So if it points to heap-allocated memory, and this object holds the only pointer to that memory, then you need to free it to avoid a memory leak.
If you find yourself writing a destructor in C++ that needs to free more than one thing, then you've probably designed the class badly. There are almost certainly exception-safety errors elsewhere in the class: it's possible to get the code right, but if you're experienced enough to get it right then you're experienced enough to make your own life easier by designing it differently ;-). The solution is to write classes with a single responsibility -- to manage a single resource -- and use them as member variables. Or, better, to find library classes that manage the resource you're using. shared_ptr is pretty flexible.
"need you destroy non-heap variables"
There is no such thing in C++ as "heap" and "non-heap" variables. Destroying a pointer does not free the thing pointed to, for the obvious reason that nothing in the type of a pointer tells you how the thing it points to was allocated, or who "owns" it.

You need to understand three things about destructors. Say you have an object t of class T with three members.
class T
{
A a;
B b;
C c;
// ...
} t;
Destructing t ALWAYS means calling the following destructors in that order: ~T(), ~C(), ~B(), ~A(). You cannot influence these semantics. It is impossible to prevent the destruction of the members. This ALWAYS happens, no matter if you define ~T() manually or if the compiler generates it.
Implicitly generated destructors are ALWAYS a no-op. However, as stated in point 1, the destructors ~C(), ~B() and ~A() will still be executed afterwards.
The destructors of scalar types, especially C-style pointers, are ALWAYS a no-op. This is the sole reason why you almost always need to write the destructor (and the copy constructor and the assignment operator) manually when you have a C-style pointer member -- after ~T() has finished, destructing a C-style pointer member does NOTHING, so any cleanup intended on the pointees has to be done in ~T().
I hope this clears things up for you.

What potential memory leaks won't an implicit destructor handle? I know that if you have anything stored on the heap it won't handle it, and if you have a connection to a file or a database, that needs to be handled manually. Is there anything else? What about, say, non-base data types like vectors?
To put it simply, you are correct. The only thing not handled by the implicit destructor is memory allocated in the form of a pointer or another type of resource that needs to be released explicitly.
With regard to vectors or any other class type objects; all classes have a destructor which takes care of releasing their data. The destructor of an object of this type is called when it goes out of scope. All basic data types like: int, float, double, short, bool etc are released in similar fashion.
Also, in an explicit destructor, need you destroy non-heap variables which would have been destroyed by the implicit, or are they handled automatically?
The answer to this is that they are handled automatically, in fact you should never ever try to explicitly call the destructor of an object.
In an implicit destructor the following occurs:
Each of the member variables of the class have their destructors called in turn.
In an explicit destructor the following occurs:
The body of the explicit destructor is executed
Each of the member variables of the class have their destructors called in turn.
So you can see that an explicit destructor is much the same as an implicit one, except that you can take any necessary manual intervention.
Now as a bit of advice with regard to managing memory allocated objects you should pretty much always use RAII (resource acquisition is initialisation). The crux of this is smart pointers, these are pointers that are deleted correctly when they go out of scope just like non heap allocated objects. Ownership becomes an issue once you start using them but that's a story for another day. A good place to start with smart pointers is boost::shared_ptr. (btw if you haven't got on board with boost yet and you write c++ code do yourself a favour...)

The implicit destructor calls the destructor on all member variables.
If you have a raw pointer, its destructor does nothing. So if you own the memory it points to, you have to release it explicitly.
The same applies to any other resource, or any other action you wish to take not implied by the default destructor of the member variable.
The default destructors of members are still called, so vectors, auto_ptrs, files opened using std streams or other C++ libraries all get destroyed. The moral is to wrap any OS objects which need releasing in C++ classes which tidy themselves up, so that application classes don't have to worry about it.

A class' destructor will implicitely call the destructors of all non-static members, then the destructors of virtual base classes, then its own code.
If you have STL containers as class members, you don't have to do anything explicitely--they will free their own memory in their destructors.

You're already making wrong assumptions. If my class holds heap-allocated data using an std::auto_ptr<Data>, the implicit dtor will handle it. No memory will be leaked. The reason is that the implict dtor, like any other dtor, will call the dtors of all members and base classes.
Now, a good class design holds all important resources as members with proper dtors. As a result, the dtor body needs to do nothing to prevent resource leaks. Of course, there is one exception to that rule: resource managing classes themselves manage precisely one resource, and therefore clean up that one resource in their dtor.

Related

What does the destructor of primitive types actually do? [duplicate]

This question comes from me trying to understand the motivation for smart pointers where you make a wrapper class around the pointer so that you could add a custom destructor. Do pointers (and ints, bools, doubles, etc.) not have a destructor?
Technically speaking, non-class types (C++ term for what often called 'primitive type' in layman words) do not have destructors.
C++ Standard only speaks of real destructors in context of classes, see [class.dtor] in C++ standard. Aside from that, C++ also allows to call a destructor on a non-class object using the same notation, i.e. following code is valid:
void foo(int z) {
using T = int;
z.~T();
}
This is called 'pseudo-destructor' and exists exclusively to allow writing generic templated code to deal in the same manner with class and non-class types. This call does nothing at all. This syntax is defined in [expr.prim.id] in C++ standard.
Primitive types (and compounds thereof) have trivial destructors. These don't do anything, and have special wording that allows them to be skipped altogether in some cases.
This, however, is orthogonal to why C++ has smart pointers. A raw pointer is non-owning: it points at another object, but does not affect its lifetime. Smart pointers, on the other hand, own (or share ownership of) their pointee, tying its lifetime to their own. This is what is implemented inside, among other special functions, their destructor.
In addition to the answers given here so far, since C++20 the pseudo-destructor call on a non-class object will always end its lifetime. Consequently accessing the object's value after the call will have undefined behavior. This does not mean however that the compiler has to emit any code for such a call. It still effectively does nothing.
No, pointers don't have destructors. An object referenced through a plain old pointer has to be deleted to avoid memory leaks, and the object's destructor is called then, but the compiler won't call delete automatically, even when a pointer goes out of scope - what if another part of your program also had a pointer to the same object?
Smart pointers aren't about calling a custom destructor, they're about ensuring that things get cleaned up automatically when they go out of scope. This 'cleaning up' might be deleting owned objects, freeing any malloced memory, closing files, releasing locks, etc.
Destructors are used to free the resources that an object may have used.
For pointers, you don't need delete if you are not allocating new memory from the heap.
C and C++ have two ways to store a variable: stack and heap.
Stack is for static memory, and the compiler takes care of that. Heap is for dynamic memory, and you have to take care of this if you are using it.
When you do primitive type declarations, stack memory is allocated for the variables.
When you use new to declare an object, this object is stored on the heap, which you need to delete it when you are finishing using it, or it would be a memory leak.
Basically, you only need delete if you new something.

Why can't classes with a destructor be memcpy'ed

The rules of C++ say that it's legal and will work to copy an object or a POD type using memcpy.
They further say that a POD can't have a (non-trivial) destructor. Why is this and why would the mere addition of a destructor change the class in such a way that using memcpy would not work?
// Perfectly fine to copy using memcpy
struct data
{
int something;
float thing;
};
// Not allowed to copy using memcpy
int var;
struct data
{
int something;
float thing;
~data() { var = 1; }
};
Why would simply adding the destructor make it impossible to memcpy the struct's data? I can't imagine that this would require altering the data layout in any way.
I'm not interested in being told don't do this, I have no intention to do so... I understand I can't do this because "the standard says so" but I'm wondering what the reason the standard says so is as it doesn't seem a necessary restriction to me and want to understand the reasons.
EDIT People seem to be misunderstanding my question. I'm not asking if it's a good idea or not to use memcpy. I'm asking what is the reasoning behind making it illegal if there is a non-trivial destructor. I can't see what difference it makes and want to understand why this restriction exists. Most of the reasons I've been given about it being a bad idea apply just as much if there is a destructor or not.
In layman's terms:
Why would simply adding the destructor make it impossible to memcpy the struct's data?
It doesn't make it impossible, just illegal.
I can't imagine that this would require altering the data layout in any way.
Probably won't, but it's allowed to. Because the class is no longer a POD (i.e. a c struct) it's now a c++ class.
Classes have different rules to PODs. Since we cannot predict how the compiler will go about coding them up, we can no longer reason about the outcome of memcpy.
Non-trivial destructors typically reverse some non-trivial action performed in a constructor (or other member functions) that affect the object state.
memcpy() copies the bits that make up the object. If the behavior of a constructor would give a different set of bits, then the destructor on that object will try to reverse some action that has not actually occurred.
A typical example is a class who's constructors allocate some resource (e.g. memory), other member functions ensure that resource remains in a sane state, and the destructor releases that resource. Copying such an object using memcpy() will copy the handle of that resource, rather than creating a new instance of that resource for the copied object [which is what the copy constructor of such an object typically does]. The destructor - eventually - will be invoked for both the original and copied objects, and the resource will be released twice. For memory (e.g. allocated using C's malloc() or C++'s operator new) releasing twice gives undefined behaviour. For other resources (file handles, mutexes, other system resources) the result varies, but - on must systems - it is generally inadvisable to deallocate a single something twice.
The other problem is that a class may have base classes, or have members, that themselves have non-trivial constructors and destructors. Even if the class itself has a constructor which does nothing, destroying an object invokes destructors of all members and bases. Copying such an object using memcpy() affects those base classes or members in the way I describe above.
Only objects which are trivially copyable can be copied using memcpy. A class with non-trivial destructor is not trivially copyable.
Suppose for an example, your class has a pointer as one of its member. You allocate space for that pointer in the constructor of the class. Now, you can do a variety of things in the non-trivial destructor like deleting the space you allocated. By memcpy you'll be copying the entire structure bit by bit. So two instances will be trying to delete the same pointer when their destructors are called.
This is because memcpy provides a shallow copy and if you have a non trivial dtor it is probably because your object is the owner of some resource, then a shallow copy would not provide you the right copy semantic (duplicate the ownership). Think about some structure with a pointer to something inside, the dtor should (probably) free the resource when the struct disappear, but a shallow copy will let you with a dangling pointer.
The problem is usually that when you have a destructor which does something, you also should have a copy constructor/assignment operator (look up "Rule of 3" for this).
When you memcpy, you will skip these copy operation and this can have some consequences.
E.g. you have a pointer to an object and delete it in the constructor. You then should also specify a copy operation so you copy the pointer/object there too. If you use memcpy instead you have 2 pointers to the same instance and the second destruction would cause an error.
The compilers cannot know what you do in your destructors and if special behavior is needed so it's pessimistic and is seen as a non-POD type anymore. (even if you do nothing in the destructor).
A similar thing happens with the generation of move-assignment/move-constructors when you declare a destructor in a class in c++11.
The problem arises when memory is owned by the class: you should not memcpy a class that owns memory (even if it has no destructor) take for instance:
https://ideone.com/46gFzw
#include <iostream>
#include <memory>
#include <cstring>
struct A
{
std::unique_ptr<int> up_myInt;
A(int val)
:
up_myInt(std::make_unique<int>(val))
{}
};
int main()
{
A a(1);
{
A b(2);
memcpy(&a, &b, sizeof(A));
std::cout << *a.up_myInt << std::endl;
//b gets deleted, and the memory b.up_myInt points to is gone
}
std::cout << *a.up_myInt << std::endl;
return 0;
}
which results in
stdout
2
0
stderr
*** Error in `./prog': double free or corruption (fasttop): 0x08433a20 ***
As b goes out of scope, the data it owned is deleted, a points to the same data, hence fun times (same happens if your class contains basically any other stl container so never ever memcpy an stl containter either.)

Does a C++ destructor always or only sometimes call data member destructors?

I'm trying to validate my understanding of C++ destructors.
I've read many times that C++ supplies a default destructor if I don't write one myself. But does this mean that if I DO write a destructor that the compiler WON'T still provide the default cleanup of stack-allocated class fields?
My hunch is that the only sane behavior would be that all class fields are destroyed no matter what, whether I provide my own destructor or not. In which case the statement I've read so many times is actually a little misleading and could be better stated as:
"Whether or not you write your own destructor, the C++ compiler always
writes a default destructor-like sequence to deallocate the member
variables of your class. You may then specify additional
deallocations or other tasks as needed by defining your own destructor"
Is this correct?
When an object is cleaned up in C++, the language will
First call the destructor for the class, then
Call the destructors for all the fields of the class.
(This assumes no inheritance; if there's inheritance, the base class is then destroyed by recursively following this same procedure). Consequently, the destructor code that you write is just custom cleanup code that you'd like to do in addition to the normal cleanup code for individual data members. You won't somehow "lose" the destructors for those objects being called as normal.
Hope this helps!
Yes -- any object contained within your object will be destroyed as part of destroying your object, even if/though your destructor does nothing to destroy them.
In fact, your destructor won't normally do anything to destroy objects contained within the object; what it typically does is destroy objects that are remotely owned via something in the object (e.g., a pointer to an object, a handle to a network or database connection, etc.)
The only exception to this that's common at all is if your object contains a buffer of some sort, and you've used placement new to construct something into that buffer. If you use placement new, you normally plan on directly invoking the dtor as well. [Note that "common" is probably overstating how often you see/use this--it's really quite uncommon, but the other possibilities are much rarer still.]
Yes. Even if you DO write a destructor, the C++ compiler will create a sequence. Consider the following code:
class foo{
int a;
}
Write a destructor that deallocates a, a stack-allocated variable... its impossible. Therefore, even if you write your own destructor, a C++ compiler MUST generate one to deallocate stack objects.

Destructor in class

I have created a class, and according to the textbook Accelerated C++ by Andrew Koenig and Barbara E. Moo,
The work of the destructor is to do any cleanup that should be done whenever an object goes away. Typically this cleanup involves releasing resources, such as memory, that the constructor has allocated.
I am trying to write a destructor, and I'm getting confused by all the code floating out there. Sometimes a simple deconstructor like this is used ~MyIntArray() {} and sometimes there are things between the {}.
What is the rule behind putting things between the curly brackets or not? Is it just containers e.g. lists, arrays, vectors, pointers that need to be placed between the curly brackets (these are the things I see in code examples out there).
edit: this is my class in case that's needed
class msgInfo
{
public:
msgInfo();
msgInfo(int, int, int, std::string, std::list<int>);
private:
int source_id;
int dest_id;
int priority;
std::string payload;
std::list<int> nodePath;
};
Rule 1:
Rule of three in C++03 or rule of five in C++11.
If your class needs a user defined copy constructor or a copy assignment operator then it most likely needs a user defined destructor.
When do you need either of these 3?
When your class has dynamically allocated pointer members and you need to maintain lifetime of each separate from that of another instance member. For e.g: char * member.
When you manage resources. For e.g: Open file handles, mutex locks etc.
Rule 2:
If your class is intended to be used for derivation and you need polymorphic deletion of objects then you must mark the destructor in Base class as virtual.
Well, if you allocated resources dynamically (new etc..) then in the destructor you'd want to release them (delete), in your case, since all of your members are not allocated dynamically, your destructor can be empty ( or non existent).
Another note worth mentioning is, if you do end up implementing the destructor, and you plan on someone inherting your class, you should make it virtual.
It is a good programming practice to provide a destructor in your C++ program even if there is no explicit need for one. In your code you might not have any dynamic memory allocation, so the destructor provided is simply ~MyIntArray() {} without any code inside.
Please also read the Wikipedia article on Rule of Three in C++.
http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)
If you don't provide a destructor, the compiler will provide one for you. This automatically-generator destructor will correctly call the destructors of all of your class's data members, such as payload etc.
If you don't need to do anything beyond that then you don't need to explicitly provide a destructor. Alternatively, an empty one would work equally well.
If, on the other hand, your constructor allocates some resources (for example, connects to a database), then typically you'd need to put some code in your destructor to release that resource (e.g. disconnect from the database). This is the standard C++ idiom used to prevent resource leaks.
Your class does not have any resources that need to be dealt with in the destructor: each type is either built-in (`int) or handles its own resources (std::string,std::list`). So you do not need to implement your own destructor. The compiler will provide one that is equivalent to the empty braces one.
You would need to implement your own if your class had resources that need dealing with: dynamically allocated objects, handles or connections to sockets, databases, reference counts, etc.
One situation where it might make sense to implement an empty destructor is when you have a class which is intended to be derived from and used polymorphically. In this case, a virtual destructor is needed (there are many SO posts about that), and it is common practice to provide an empty implementation so that derived types to not have to implement it themselves when there are no resources to deal with.
virtual ~Foo() {}
A class like this doesn't need a non-trivial destructor (one, with "things between the curly brackets").
In a destructor, you must release resources, you have "manually" allocated. For example:
if you have new/new[] in the constructor and you need to free this memory in the destructor
if you have opened a file in the constructor, close it in the destructor
if you have locked a mutex in the constructor, unlock it in the destructor
Things like this.
Also, you may need some additional logic to be implemented, when an object is being destructed. Depends on what you're trying to do.
A definition of a destructor should, as far as I know or am concerned, should always look like this:
~msgInfo() { /* free stuff */ }
A constructor on the other hand may look like this:
msgInfo(): m_var1(0), m_var2("Initialize") { /* further initialization */ }
Where what comes between : and { is member variable initialization.
In the destructor you should deallocate anything which was dynamically allocated elsewhere in the class, hence the : notation is no good, since you probably need to do delete on the objects.
In your code you might not have any dynamic memory allocation,so you don't need to provide a destructor.

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.