Deleting dynamically allocated memory from a map - c++

I've got a map of dynamically allocated object and was wondering what the best way of deleting them was?
I was thinking maybe an interator? Something like:
studentlist::const_iterator deletemem = studentmap.begin();
for(studentlist::const_iterator deletemem=studentmap.begin(); deletemem!=studentmap.end();++deletemem)
{
Record *z=deletemem->second // Record is the type of object stored in the map student map
delete z;
}
But i'm not sure, any help would be much appreciated!

Your code looks fine. However, manually deleting is probably not exception-safe. You might consider using share_ptr (either the one from Boost, or, if you use C++0x, the standard implementation) for the values or using a boost::ptr_map.
Edit: To delete the actual data in the map, call studentmap.clear() after deleting all the contents. This will remove all elements from the map.
Edit 2: The problem with your solution arises when, for instance due to an exception, your cleanup code does not get called. In that case you leak memory. To overcome this problem, you can employ the RAII-idiom. Two possible ways of doing this are described above.

A better solution would be to encapsulate your dynamically allocated memory inside another object which is stack allocated. This could either be one of your own invention or you could use the shared_ptr class from the new C++ standard or from boost.

Your code should work, but you should clear the studentmap at the end.
Of course, you have also to invalidate any other object that should hold a copy of the pointers you are deallocating, otherwise your application will probably crash.

Related

Safe array deletion

I'm new to C++ and i'm not absolutely sure how to deal with arrays and pointers in a safe way. In my class I got a member called items:
Item * items;
in my class method called read() I open a file and read the items from this file. I allocate the space accordingly:
items = new Item[item_count];
item_count is given as a variable in the file and is read in advance before creating any items. In the deconstructor in my class I release the memory like this again:
delete[] items;
But if i call the method read() twice before my deconstructor is executed the memory for the first array will not be released properly. I would like to release it in the read method in advance before allocating new memory. But how do I check if some memory is already allocated for the array items?
EDIT: I know there are many other possibilities out there with more 'modern' approachs and more comfortable solutions. But in this case we where explicitly told to use pointers and arrays (education purpose only).
In modern C++, "the safe way" is to avoid raw pointers and raw arrays entirely.
Declare your variable like this:
std::vector<Item> items;
Allocate the space like this:
items.resize(item_count);
In the deconstructor in your class, no code is necessary to release this memory. It's handled automatically.
The reuse of items that you describe in your question will work.
Unless you have some strong reason not to do so, just use std::vector for arrays in C++:
#include <vector> // for std::vector
....
std::vector<Item> items;
In this way, you don't have to explicitly call delete[] to release vector items' resources; it's just done automatically thanks to vector's (and Items') destructors.
This helps building code that is structurally incapable of leaking resources.
You can create a vector of itemCount Items using something like:
std::vector<Item> items(itemCount);
or you could dynamically resize the vector using its resize() method, e.g.:
items.resize(itemCount);
In c, normally you initialize the pointer to NULL so you can check whether or not it points to valid memory, and then after deallocation you immediately set it back to NULL.
Failing to do so, may cause problems, like dereferencing an already deallocated pointer (they're called dangling pointers), so you must be careful.
In c++ you should use nullptr which is equivalent to c's NULL.
Also, there are smart pointers in c++, i.e. pointers that can do this automatically.
Edit: (the answer above was edited) as suggested from the comments, and although this same idea is correct, you should not use NULL in c++, instead use nullptr which has the same functionality, but takes care about the fact that in c++ void * is not automatically converted to any other pointer type like in c.
This Stack Overflow Answer has the details, and also an example that would definitevely convince you and me to use nullptr instead.

How to use STL map?

I have a private field
std::map<std::string, std::multiset<GraphObject*>>* the_Map;
How can I allocate memory for it and insert a GraphObject?
Do I have to use the new operator?
the_Map = new map<string,multiset<GraphObject*>>;
And how can I insert a new GraphObject?
It's part of a datastructure and I really need a pointer to a map.
How can I allocate memory for it and insert a GraphObject?
It doesn't want to be a pointer at all; just make the map itself a member of the class and memory allocation will happen automatically.
Correctly inserting an object is rather fiddly, since you're storing pointers there too. If it doesn't need to be a pointer, then storing objects would make your life much easier. If it really does have to be a pointer (e.g. because GraphObject is a polymorphic base class), I would recommend storing smart pointers: std::unique_ptr, or std::tr1::shared_ptr or boost::shared_ptr if you're stuck in the past.
If you really, really need to use raw pointers for some insane reason, then the closest you can get to an exception-safe insertion is probably:
GraphObject * object = new Whatever(...);
try {
the_Map[key].insert(object);
} catch(...) {
delete object;
throw;
}
or if you don't care about the possiblity of memory leaks on insertion failure:
the_Map[key].insert(new Whatever(...));
Also don't forget to delete each object when you remove it; that won't happen automatically.
I really need a pointer to a map.
No you don't. But if you really believe you do, and want to ignore everyone's advice not to, then you'll need an actual map to point to. I would recommend that you make this map a member of the class, so that its lifetime is managed automatically.
If you really want to make life difficult for whoever maintains the code, then I suppose you could allocate one with new. In that case, remember to delete it when you've finished with it; probably in the class destructor. And if you do that, remember the Rule of Three and implement or delete the copy constructor and copy-assignment operator, since the default implementations will do the wrong thing.
Why you're storing a ::std:multiset of GraphObject *'s is a bit obscure, but lets roll with that.
This is an answer that is really trivially answered by documentation, but there is no question too dumb for StackOverflow, so...
the_Map = new map<string,multiset<GraphObject*>>;
That is indeed how you allocate memory for your map. It's generally not a good idea to have bare pointers to things lying around, but you insisted, and that's how you do it. That means you will have to remember to delete it at some point as well. And you will have to make sure that the copy construct of the class that holds the pointer does the right thing (and said right thing will be fairly complicated).
You have an interesting problem now. You are storing a multiset in each map entry. Fortunately this multiset will automatically be created and initialized to empty when a previously unknown key is accessed. OTOH, your use of bare pointers means that you have an exception safety problem. It's possible to leak memory if an exception is thrown anywhere along the way. So you have to catch any exceptions and clean up your object:
GraphObject *tmp = new GraphObject;
try {
(*the_Map)[key].insert(tmp);
} catch (...) {
delete tmp;
throw;
}
The fact your question is so basic makes me question your assertions about needing to use pointers. And I really wonder if you wouldn't rather have a multimap rather than a map from string -> multiset. But, you're adamant about the general form of your data structure. So the above is how you'd use it.
I'll also say that this data structure's copious use of bare pointers is a pretty bad idea. You'll have to write a pretty sophisticated functions to properly deconstruct or copy the whole mess.
Edit: sigh Coding at 4am on a data structure I would never create myself led me to write some very stupid code. The current version is much better. Though this answer is really much better than mine.

C++: Pointer as a key in a hashtable

Are there any problems using pointers as hashtable keys during program run? (no need to store to disk and use it later as that causes obvious problems)
There are many circumstances where I need to quickly know whether an object belongs to some object manager. A quick way to check it is to store every object in an object manager in a hashtable where the object's pointer is the key to the actual object: E.g, HashTable
No, there are no problems. It's just like storing an int.
A pointer has got a value that doesn't change and that uniquely identify a resource.
There of course be problems if you don't use well your pointers, but this is another, uncorrelated thing.
It should work well enough. Are you seeing any problems? Maybe you should just try and see. :)
Off the top of my head - If mem space pointed to by your hashtable is deallocated without first deleting the references to mem space pointed to by your pointers, there is going to be memory leaks hanging around.

A destructor - should I use delete or delete[]?

I am writing a template class that takes as an input a pointer and stores it. The pointer is meant to point to an object allocated by another class, and handed to the this containing class.
Now I want to create a destructor for this container. How should I free the memory pointed to by this pointer? I have no way of knowing a priori whether it is an array or a single element.
I'm sort of new to C++, so bear with me. I've always used C, and Java is my OO language of choice, but between wanting to learn C++ and the speed requirements of my project, I've gone with C++.
Would it be a better idea to change the container from a template to a container for an abstract class that can implement its own destructor?
If you don't know whether it was allocated with new or new[], then it is not safe to delete it.
Your code may appear to work. For example, on one platform I work on, the difference only matters when you have an array of objects that have destructors. So, you do this:
// by luck, this works on my preferred platform
// don't do this - just an example of why your code seems to work
int *ints = new int[20];
delete ints;
but then you do this:
// crashes on my platform
std::string *strings = new std::string[10];
delete strings;
You must document how this class expects to be used, and always allocate as expected. You can also pass a flag to the object specifying how it should destroy. Also look at boost's smart pointers, which can handle this distinction for you.
Short answer:
If you use [] with new you want to use [] with delete.
//allocate some memory
myObject* m = new myObject[100];
//later on...destructor...
delete m; //wrong
delete[] m; //correct
That was the bare bones, the other thing you could look at is boost. Also quite difficult to answer considering you are not sure if its an array or single object. You could check this though via a flag telling your app whether to use delete or delete[].
As a general development rule, you should stick to a design where the class which calls new should also call delete
You shouldn't delete it at all. If your class takes an already initialized pointer, it is not safe to delete it. It might not even point to an object on the heap; calling either delete or delete[] could be disastrous.
The allocation and deallocation of memory should happen in the same scope. Which ever code owns and initializes the instance of your class is also presumably responsible for initializing and passing in the pointer, and that is where your delete should be.
Use delete if you allocated with new.
Use delete[] if you allocated with new[].
After these statements, if you still have a problem (maybe you want to delete an object that was created by someone else), then you are breaking the third rule:
Always delete what you created. Corollary, never delete what you did not create.
(Moving my comment into an answer, by request.)
JonH's answer is right (about using array destruction only when you used array construction), so perhaps you should offer templates: one for arrays, one not.
The other answer is to avoid arrays and instead expect a single instance that may or may not be a proper collection that cleans up after itself, such as vector<>.
edit
Stealing blatantly from Roger Pate, I'll add that you could require the use of a smart pointer, which amounts to a single-item collection.
If you have a class that takes a pointer it's going assume ownership of, then the contract for the use of the class needs to include one of a couple things. Either:
the interface needs to indicate how the object the pointer is pointing to was allocated so the new owner can know how to safely deallocate the object. This option has the advantage of keeping things simple (on one level anyway), but it's not flexible - the class can't handle taking ownership of static objects as well as dynamically allocated objects.
or
the interface needs to include a mechanism where a deallocation policy can be specified by whatever is giving the pointer to the class. This can be as simple as providing a mechanism to pass in a functor (or even a plain old function pointer) that will be called to deallocate the object (preferably in the same function/constructor that passes in the pointer itself). This makes the class arguably more complicated to use (but having a default policy of calling delete on the pointer, for example, might make it as easy to use as option 1 for the majority of uses). Now if someone wants to give the class a pointer to a statically allocated object, they can pass in a no-op functor so nothing happens when the class wants to deallocates it, or a functor to a delete[] operation if the object was allocated by new[], etc.
Since pointer in C++ does not tell us how it was allocated, yes, there's no way to decide what deallocation method to use. The solution is to give the choice to the user that hopefully knows how the memory was allocated. Take a look at Boost smart ptr library, especially at shared_ptr constructor with second parameter, for a great example.
A smart pointer like boost shared_pointer already has this covered, could you use it? linky
Put simply, given only a pointer to dynamically allocated memory there is no way of determining how to de-allocate it safely. The pointer could have been allocated in any of the the following ways:
using new
using new []
using malloc
using a user defined function
etc.
In all cases before you can deallocate the memory you have to know how it was allocated.

Should I delete vector<string>?

I've painfully learned during last few days a lot about programming in c++.
I love it :)
I know I should release memory - the golden "each malloc=free" or "each new=delete" rules exist now in my world, but I'm using them to rather simple objects.
What about vector ? Wherever I can, I'm using vector.clear() but that clearly isn't enough, because I'm having huge memory leaks.
Could you guide me on how should I treat this thing?
*Edit
Thanks, your comments made me think about the alghorithm of this application and I'll be able to eliminate the vector totally. :O
Sorry - I started explaining what is my use case here and I found out what I really need. It's like that when you code last 3 days for 18 hours a day :|
*Edit 2
This is crazy. By small changes in code, I've eliminated memory usage from 2x130 mb (constantly growing) into 2x 13,5mb, constant size. Thanks for making me think about that in another way.
Btw. such self code review got a name - anyone remember that? It's when you ask anyone (even your mother or dog) and start explaining what's your problem - and suddenly you solve this 5 hour problem yourself, just by trying to look at it from other point of view, or just by trying to summarize what's it all about. I often find myself being catched on that...
The rule is that when you clear a vector of objects, the destructor of each element will be called. On the other hand, if you have a vector of pointers, vector::clear() will not call delete on them, and you have to delete them yourself.
So if all you have is a vector of strings, and not pointers to strings, then your memory leaks must be caused by something else.
You don't need to be doing this. std::string cleans itself up, so the strings are not your problem. Remember that YOU didn't use new so YOU don't have to use delete.
You should probably learn about RAII - it makes allocation and deallocation much simpler. You'll avoid memory leaks this way.
Calling v.clear() will destroy all objects that are currently held inside v, but it will not release the memory (it is assumed that the vector will soon be filled again).
If you really want to free the memory, the idiom is
vector<string>().swap(v);
This will create a new (temporary) vector and swap its contents with v. The temporary vector is then destroyed, freeing the memory along with it.
Deleting elements from STL containers is guaranteed to call destructors on these elements.
However, if you have a container of some pointer-to-T type, then you still have to free the pointed-to memory yourself (in this case, the "destructor" for the pointer gets called, which is a no-operation).
If you do not want to manually manage memory in this case, consider using a smart-pointer solution or a pointer container.
The vector (like all standard containers) owns the objects inside it.
So it is responsible for destroying them.
Note: If you vector contains pointers then it owns the pointers (not what the pointers point at). So these need to be deleted. But there are easier ways.
You could use a vector of smart pointers. In fact you should be using some form of smart pointer for nearly everything. If you are using pointers you are probably still programming like a C programmer.
So:
std::vector<int> data; // clear is fine.
std::vector<int*> data1; // Now things need to be deleted.
// alternative 1:
std::vector<boost::shared_ptr<int> > data2; // The shared pointer will auto
// delete the pointer.
// alternative 2:
boost::ptr_vector<int> data3; // Here the container knows that
// it is holding pointers and will
// auto de-reference them when you
// its members.
But it sounds like you need to start thinking about learning about smart pointers.
int* x = new int(5);
// Do stuff.
*x = 8;
delete x;
// --- Instead use a smart pointer:
std::auto_ptr<int> x(new int(5));
// Do stuff.
*x = 8;
// No delete (the auto ptr handles it.
If you have a vector and it goes out of scope, all objects in the vector are destroyed. There isn't really a need to call clear() unless you want to dump the contents and reuse the vector.
However if you by any chance are using something like a vector then the destructor of the objects being pointed to will not be called as the vector destructor doesn't follow the indirections represented by the pointers.
All that said, have you actually confirmed that you've got genuine memory leaks and that they are caused by the data in the vector?
Give a use case. The destructor on the string is getting called by vector::clear. Your problem lies elsewhere my friend.
also check out:
Does std::vector.clear() do delete (free memory) on each element?
As rlbond suggested, use RAII.
It's a good rule of thumb to never put new and delete calls into your main code flow. Always try to put them into objects so that the object destructor can free what needs to be freed. In this way, you avoid needing to remember to call delete and it makes your code exception safe (assuming that you make your object's operations exception safe).
For example, if you had a vector of pointers to STL strings or C-style character arrays, put that into a StringContainer (use a better name) and have the StringContainer hold a vector and in the StringContainer destructor run a for loop to delete each string in the vector.
You can make the vector inside the StringContainer a public member and mess around with it directly, but it's even better design to make it private or protected and add some member functions to manage the string* vector.
So your main C++ program should never see a new or delete anywhere. Instead it should have a lot of stack allocated objects, auto_ptrs and shared_ptrs.