How to properly define destructor - c++

I am relatively new to C++ (and programming in general) so please forgive me if the question is not perfectly clear immediately.
What I have is a program in which a certain number of objects of a internally defined class [let's call this "class1"] are created.
The program works perfectly fine and the objects do what they should.
The problem that I am currently trying to solve is the following: these objects are not destroyed (and thus memory is not de-allocated) until the program exits, but I need that memory earlier.
Among the other members of the class there are objects of other internally defined classes (who also have members that are objects of a third class).
My question is the following: how do I properly define a destructor for the objects of "class1" so that all the data is cancelled and the memory deallocated?
I found out (probably this was obvious for you already) that a destructor like
class1::~class1(void) {
}
won't work (I defined similar destructors for all internally defined classes).
Reading around I understood that my mistake could be that that is a destructor that does nothing. How do I solve this?
Thanks to anyone who will answer/help/comment.
Federico

In C++ you need to free the memory manually. There's no garbage collector. You obviously need to free the memory manually inside your destructor. If you allocated the memory using new, you need to use delete for each resource you allocated with new inside the deconstructor, for example:
class1::~class1(void)
{
delete resource1;
delete resource2;
etc...
}

If you are allocating memory dynamically you need to free it in destructor, but better solution would be to use some smart pointer to hold dynamic data - std::auto_ptr or std::shared_ptr. Then you will not need to explicitly free memory - this will be done automatically in smart pointer destructor.

First you should try to allocate your objects on the stack:
Object obj;
so you don't have to worry about memory allocation. The disadvantage is that the object life is limited to the current scope.
If that's not good for you, you should consider using smart pointers. If that's not an option use new / delete to create / destroy your objects. But you have to be careful, every new should lead to a delete at some point in time..

Memory on stack
If there is no heap-allocated object inside your class, there is no need for you to explicitly define the destructor of your class. The compiler-generated one should handle the job quite well, i.e., call destructors for base class objects and member objects, etc.
Memory on heap - manual memory management
If there is any heap-allocated objects inside your class, you need manually deallocate them in your destructor. Make sure you have them deallocated properly at all possible exit points, e.g., handle exceptions and deallocate resources.
Memory on heap - RAII
Alternatively, you may use some well-defined RAII class to handle the resource management for you automatically, e.g., scoped_ptr, scoped_array in Boost, shared_ptr in STL, etc.

Related

Destructors and the delete() method in C++

So I added a destructor function to a class in C++.
class object { ~object() };
And declared an object with the new method, thereby allocating it on the heap
object *pointer = new object;
Do I still need to use the
delete(object);
method at the end of the program? (Isn't the destructor already responsible for exactly this?)
You still must call delete(object). Destructor is responsible for how to delete an object and delete(object) is responsible for when to delete it. But in modern C++ usage of naked pointers is considered a really bad practice. You should consider using smart pointers, such as std::unique_ptr for managing memory.
You have 2 different kinds of memory. The stack and the heap.
Everything on the stack deletes itself when you go out of scope (one of the steps of deletion is calling the destructor)
Everything which is on the heap (you call malloc, new, etc) you have to delete explicitly by yourself (which will then result in the destructor being called).
Smart pointers like unique_ptr / shared_ptr are a modern c++ way to get rid of the manual deletion on heap objects and to make sure they get deleted when the objects are not needed anymore.
Destructors are a way of customizing the clean-up process (add logging, provide cleanup as per rule of three/five, etc.). You still need to delete, otherwise you'll have a memory leak.
That being said, it's frowned-upon and considered a bad practice to write code that actially needs news and deletes (especially the latter). If you need to store an object on the heap, use unique_ptr/shared_ptr or a container like vector.
If you have the time, I suggest you watch Herb Sutter's talk from C++Con 2016: Leak-Freedom in C++ for guidance.
The destructor gets called when the objects lifetime is over. For heap allocated objects this means when you delete them.
So a call to
delete(object);
calls your descructor and frees the allocated memory.
Yes, you must need Delete method.
Default destructors call destructors of member objects, but do NOT delete pointers to objects. Thus, You need to write destructors that explicitly call delete. Like,
delete pointer;
Do I still need to use the delete(object); method at the end of the program?
Yes.
Isn't the destructor already responsible for exactly this?
No.
Your delete ptr; is what invokes that destructor. If you hadn't declared a destructor, one would have been declared for you, so that made no difference.
You don't need to write delete ptr; when your object has automatic storage duration (very loosely: "when you didn't create it with new"), because then the equivalent is done for you.
But in both cases the destructor is called.
A new and a delete expression (which are not the new and delete operators) are invoking two calls:
new:
1) call the operator new for memory allocation
2) invoke the appropriate constructor
delete:
1) invoke the destructor
2) call the operator delete for memory deallocation
Hence you have to pair any new with a delete, to avoid resource (memory) leaks.
However, object construction and destruction does not require new and delete.

Dynamically allocated member variable. What's the point?

I'm totally new to C++. I would like to ask about the following.
If a member variable is dynamically allocated in the constructor. Should it always be deleted in destructor? If so, then how is the variable's lifetime "elongated"? If not, how should memory leak be handled otherwise?
I couldn't find any source to address this issue explicitly.
Reasons to allocate a member dynamically are
The size of an array may be non-constant
The member could be very large, such that there is not enough memory on the stack
The member is polymorphic, as commented by MSalters
But, as Alf already pointed out in a comment, it is preferable to use a smart pointer. This has the advantage that you don't need to explicitly delete that member in the destructor, and in the case of a shared_ptr, you can elongate the liftime as needed, the smart pointer takes care of the destruction.
Should it always be deleted in destructor?
Not a necessity - you can free up the memory as soon as the work is done by some other function, if you are sure it won't be used any further. But, you must anyway call this destruction routine from destructor also to avoid memory leak. Ideally, you'd also need to provide another function for ReAllocate the memory.
In short, it all depends on your class and what are you implementing.
Let me take some post-modern approach and say "you don't have to worry about it anymore"
use unique_ptr if only the creating-object is incharge of that resource, use shared_ptr if many objects share that resource. use STL containers for all other possible uses.
use new and delete only if you're writing something extremely low-level or implementing a container from scratch. for all other cases, view dynamic memory allocation (via malloc and new) as deprecated.

Will using shared_ptr for returning pointers from a method always save me from memory leaks?

I'm a c++ newbie, my code currently new's up on the heap in several places without calling delete. I know I need to do something about this.
My typical usage is where I new up a class instance in another classes member method then the method returns the pointer to the object.
If i change the return types from MyType* to std::tr1::shared_ptr will this fix my code to not leak memory?
Thanks a lot.
Edit:
Also likewise, I currently store new'ed up objects as MyType* as a value in a std:map. This map is a private member to a class instance. If I simply change this to std::tr1::shared_ptr will this clear up these when it's owner (class) falls out of scope?
Thanks again
It's a reasonable band-aid, sure.
A shared pointer is a reference-counted pointer. So as long as one or more shared_ptrs exist pointing to an object, that object will be kept alive. The problem occurs if you have circular references. Then the reference count will never reach 0, and the object(s) will never be deleted.
So shared_ptr * still* require you to understand what you're doing and think about object ownership, as you always have to do in C++. But it simplifies some otherwise complex scenarios, where determining ownership is hard.
But the real fix to your problem is to:
minimize how much you allocate with new. Can the object instead be stored on the stack? Can the object be rewritten as a RAII class, so that a small wrapper object is allocated on the stack (or elsewhere with automatic storage duration), and which, through its constructors and destructors, manages a heap-allocated memory resource? Then, as long as that object exists, its allocated memory will be preserved, and once it is destroyed, it will delete its allocated memory.
when you allocate objects with new, put them in one of the smart pointer classes. shared_ptr is popular because it is the one that comes closest to looking like a garbage collector, but it isn't, and if you treat it as one and use it as an excuse to not think about memory management, then it won't work. Understand all the smart pointer classes (scoped_ptr and auto_ptr in C++03, or unique_ptr replacing both in C++11, shared_ptr and weak_ptr), and use the one that best fits your scenario.
think about ownership. Any time you allocate memory, you need to determine an owner, whose lifetime will control the lifetime of the memory allocation. Think about how long a lifetime your allocation needs, and have another object (whose lifetime is automatically managed, probably because it is on the stack) delete your memory when its destructor is called.
There's no quick and easy fix. The way to handle memory management in C++ is to avoid memory management. Delegate it out to your objects. If you're calling delete in your own code, you're doing it wrong. Often, you don't even need new, but if you do, assign ownership to a smart pointer immediately, and let that call delete for you.
As a rule of thumb, unless you're a library writer, you shouldn't write either new or delete. You should virtually never use raw pointers, and only when it is absolutely necessary, use smart pointers. Let your classes do the heavy lifting. Don't be afraid to put them on the stack, pass them by value, and let them handle their resources internally.
If you are new to C++ there are a few points with pointer management you need to understand and accept, regardless of whether you're using shared_ptr or not.
It is more than likely in your use of C++ you will need to use new and assign its return pointer to a class pointer that you have declared. I believe it is advisable to take the time to understand what is going on there, even if you write a small test program and watch the constructor execute in the debugger.
If you use classes like std::string, its constructors and destructor will do string pointer management for you, but I believe it is a good idea to understand what is going on behind the scenes in that class, if nothing more than reading the documentation.
As another example, you cannot use some classes, without a lot of detailed reading of the API, or you'll get problems. I once worked at company that used a commercial class package years ago. Someone had written a multi-threaded program using this package's thread pool class.
The documentation clearly said you can't just exit with outstanding threads. Yet I saw where the author of the program did not bother to synch up and shutdown all threads on exit, and wound up throwing exceptions, when their program exited. And this was on a commercial financial product.
My suggestion is don't look to get saved from performing pointer management. There are std classes like string that can reduce your headaches, but nothing will prevent problems other than your own diligence and testing.
As long as you understand how tr1 shared pointers work, yes.
Look at Boost C++ shared_ptr<> also - it might be more what you want.

What do I have to garbage collect in a C++ destructor

I'm writing a C++ destructor (I hope that's the right term; I'm new to C++) and I'm not positive on what exactly I need to garbage collect. Let's say I have 2 pointers as instance variables do I need to garbage collect them? What about if I have an object as an instance variable? Or a pointer to an object?
I'm just a little fuzzy on what exactly needs to be deleted and what is automatically cleaned up.
Thanks
General rule of thumb is... if you called new, call delete. If you called new[], call delete[]. If you're accessing these pointers outside of the class and effectively sharing them, you'll want to be careful about the "owning" object deleteing the shared objects while they're still in use. Garbage collection isn't quite the right term. You want to destroy the object and free its memory. This is what delete/delete[] does. new/new[] allocate memory and construct an object.
In C++, there is no garbage collector. You must "manually" handle it. That's not to say that it's all tedium. You'll probably get into using smart pointers to handle some of this logic for you. See this question for more information.
You must delete every pointer you allocate with new. It's that simple, and it's that complicated; you must not lose track of any pointer allocated by new until you have deleted it.
Also, you need to make sure that if you use new[] to allocate a pointer, you call delete[] to deallocate it.
It's not about what pointers you happen to have in a class instance. You need to know who owns them (the owner is the one responsible for deleting them). If your object owns those pointers, then it should delete them. If it doesn't own them, then it shouldn't.
This is also why experienced C++ programmers avoid naked pointers where possible. Smart pointers allow you to express ownership types semantically in the language. That way, you don't have to keep track of who owns what; you know who owns it by the type of smart pointer being used.
You must call delete on every space you created using new, delete[] on every area created using new[], and free on everything you got using malloc.
You should also close any sockets you opened, and clear up any other OS resources your class owns.
Note: this is not called garbage collection. Garbage collection is when this process happens automatically, as part of a library or language runtime, not when you do it explicitly.
You should start by learning about "Resource Acquisition is Initialization" (RAII) and smart pointers (shared_ptr and unique_ptr). This is the idiom you have to know in C++ if you come from other languages.
Usual practice says that whatever you allocated in your constructor must be deallocated in your destructor (see other answers to know how). Event better, try to use values as much as possible and new as less as possible.
C++ loves the stack, and stack allocation and deallocation are automatic and cheap (no new, no delete). Use references and const-references instead of pointers.
If you really need dynamic memory, try to use one of the smart pointers.
Any memory you allocate using new operator needs to be freed.
You allocate memory by doing:
int * p1 = new int[5];
p2 = new int;
and you delete it by doing:
delete[] p1
delete p2;
If you are playing with Classes, you need to do the same thing in constructors (allocate) and destructors (deallocate).
In an ideal world, nothing. There are smart pointers and containers for every pattern. Sometimes, you will have to write your own, or augment existing implementations, but much of what you need exists already.
For an array, start with std::array and std::vector. For objects, read up on smart pointers and shared pointers. As a generalization: if you need to call delete, delete[] or free, you have usually headed down the wrong path.
You need to garbage collect all pointers that you don't no longer need. Otherwise you would have the dangling pointer problem.

when to use new in C++?

What's a good policy for when to use "new" to make an instance of a class? I've been hobby programming C++ for a while but I'm still not for sure when is the best time to do this:
MyClass thing(param1, param2);
over this:
MyClass* thing;
thing = new MyClass(param1, param2);
Any advice?
Design-wise, use automatic (stack) allocation as much as possible. Whenever you need to extend the lifetime of an object beyond a certain scope, then dynamically allocate it.
And even so, never dynamically allocate things raw. Always keep them wrapped into some sort of wrapper that implements Scope-Bound Resource Management (SBRM, first known under the dumb/awkward name Resource-Acquisition Is Initialization or RAII.) That is, dynamic allocations should be kept in automatic objects that will clean up automatically!
A good example of this is std::vector: you cannot leak the memory internal to a vector, because it's destructor is run in every scenario when memory should be free'd, and it will free it for you. auto_ptr is the first and only smart pointer available in the standard library, but it's pretty bad. Better is to use shared_ptr, or many of the other popular smart pointers available in Boost and/or TR1 and/or C++0x.
Performance-wise, objects allocated on the stack can be done so very quickly (the stack size is increased per-function-call, so all the required memory has been allocated up-front by a simple move of a pointer.) Contrarily, dynamic allocation generally requires much more time. It's quite possible to get speedy dynamic allocations with custom allocation schemes, but even the best will still be slower than stack allocation.
Occasionally, you might find you spend too much time copying objects around. In this case, it may be worth it to dynamically allocate it and merely move pointers around. However, please note I said "find". This kind of change is something you find by profiling and measuring, never guessing.
So: Automatic allocation when possible, dynamic allocation when needed.
The first approach creates a local instance on the stack that goes away when the calling function exits. The second creates an instance that stays on the heap until (and if) you explicitly release it again. The choice depends on what kind of control and lifetime you want for your object.
The rule of thumb is: if it works without new, don't use new.
In general: you don't need to use new if you plan to delete the object in the same scope. If the object is quite large, you may want to use new.
You may want to look into the difference between heap and stack memory if you want to know the details.
First, ask yourself the question, does it make sense for the object to be copied when another function wants it?
If it makes sense to copy the object, your best bet is to create everything on the stack or as member variables and then just pass copies around when needed.
If it does not make sense to copy the object, you'll need to use new form so that you can safely pass the pointer to the object. You have to use a pointer (or reference) because as noted it does not make sense to copy the object.
There are two exceptions I'm aware of:
If you know the object isn't going to be used after the current function is finished, you can create the object on the stack so that it is deleted. Just make very sure nobody holds on to a pointer to it afterwards! (I rarely find this is the case, but it happens)
If the object is used internally by another class which itself shouldn't be copied around, you can just put it in as a member variable. Since the object it is in won't be copied, and its only for internal use that will be safe.
MyClass thing(param1, param2); //memory for thing is allocated on the process stack(static allocation)
MyClass* thing;
thing = new MyClass(param1, param2); //memory is allocated dynamically on the heap(free store) for thing
The difference lies here:
int main()
{
{
MyClass thing(param1, param2); //thing is local to the scope
} //destructor called for thing
//cannot access thing (thing doesn't exist)
}
int main()
{
{
MyClass* thing;
thing = new MyClass(param1, param2);
}
//the object pointed to by thing still exists
//Memory leak
}
For large objects you must allocate memory dynamically(use new) because the process stack has a limited size.