Delete dynamic array of pointers containing duplicates - c++

What's the correct way to free the memory here?
The pointer-array contains duplicates!
class HashTable
{
Bucket<E>** index = new Bucket<E>*[indexSize];
...
}
~ExtHash( )
{
for (size_t i = 0; i < indexSize; ++i)
delete index[i];
delete[] index;
}

I would think hard about whether you want this container to be responsible for deleting the objects; it would be simpler to store them elsewhere, and just use this container to refer to them, not to manage their lifetimes.
Alternatively, you could use std::shared_ptr to manage the objects; then they will be deleted automatically when you've discarded all of them.
If you really want to do it this way, you'll need to remove the duplicates after deleting each one; something like
for (size_t i = 0; i < indexSize; ++i) {
Bucket<E> * victim = index[i];
indexSize = std::remove(index+i+1, index+indexSize, victim) - index;
delete victim;
}
[NOTE: this code may well be wrong; I certainly made a couple of mistakes writing it. If you really want to manage dynamic objects the hard way, then you'll need to test it thoroughly]

Sort index, remove adjacent duplicates with std::unique. O(N log N) and that's as good as it gets.

Use a set to remove duplicates:
std::set<Bucket*> uniqueBuckets(index, index + indexSize);
for(Bucket* bucket: uniqueBuckets)
delete bucket;

In your situation it's dangerous to store raw pointers in such way. Better use std::shared_ptr and just reset shared pointers. And after all pointers will be reseted they will be safely freed.

Perhaps like this:
~ExtHash( )
{
std::sort(index, index + indexSize);
size_t new_end = std::unique(index, index + indexSize) - index;
for (size_t i = 0; i < new_end; ++i)
delete index[i];
delete[] index;
}

Each time you create a pointer, push_back it into a vector. That vector will hold all your created pointers, and will hold each one of them only once.
Later, iterate that vector and delete the pointers.
It's like writing your own simple garbage collector.

Related

Destroy pointers to objects in array

Say I want to declare an array of pointers to a specific object like
Object *objects = new Object[size];
and then add some new objects to my dynamically allocated array
for (int i = 0; i < size; i++){
Object* obj = new obj;
objects[i] = *obj;
}
is it enough to deallocate all memory by just calling delete[] on the array, or do I have to loop through the array first and call delete on each object? Or is this stupid to do in practice?
You always have to delete everything you new in some way. That means, you would need to delete obj in every iteration to avoid leaks. Note that you never really store the Object obj points to, but a copy of it.
The way you do it right know is quite unusual and not very handy anyway: The loop you showed does nothing useful since the new Objects[size] already default constructed your Objects. In particular, it does not add any elements, they are already there. You could just leave that out. If you want to change the content of your array, e.g. do more initialization, your loop would usually look more like this
for (int i = 0; i < size; i++){
objects[i] = newValue;
}
Remember, the Objects are already there after new Objects[size]!
In practice, you would be much better of with a
std::vector<Object> objects(size);
(or maybe, if the above does not fit your usecase, a
std::vector<std::unique_ptr<Object>> objects(size);
, but I feel like that is unlikely to be the case). For a good overview of what a std::vector can do and how to use it, read the documentation. Probably most importantly for you: You can index it just like an array.
First, you have to follow the deallocation is reverse order of allocation.
So number of times new that many times delete , similarly number of times new [] that many times delete []
// Assuming objects as array of pointers [ Object **objects ]
for (int i = 0; i < size; i++)
{
delete objects[i] ;
}
delete [] objects;
And your correct allocation should go as:
Object **objects= new Object*[size];
for (int i = 0; i < size; i++) {
objects[i] = new Object;
}
Also , you should use smart pointers std::unique_ptr for hassle free memory management
std::vector< std::unique_ptr<Object> > objects ;
You are storing an array of Objects and not pointers to Object. This means that they won't be deleted when you delete the array and the memory will leak.
If you want to store pointers to Objects in your array then you need to declare it as Object **objects = new Object *[size]; and then you will have to delete all the pointers in the array.
So the better code will look like:
//Allocation:
Object **objects = new Object *[size];
for (int i = 0; i < size; i++){
objects[i] = new Object;
}
//Deletion
for (int i = 0; i < size; i++){
delete objects[i];
}
delete [] objects;
An even better solution would be to use vectors and smart pointers and then you don't need the deletion code at all.
//Allocation:
vector<unique_ptr<Object>> objects;
for (int i = 0; i < size; i++){
objects.push_back(make_unique(new Object));
}
//Deletion
//Hey where did all the code go.

Vector of pointer objects creation

I have to implement Vector<MyObject*> by calling AnotherClass::objectCollections(). So here the return type should be Vector<MyObject*>. Also I have to return each MyObject* from another function that could return MyObject*. So that it can populate the Vector. I am newbie for C++ core programming. I want to know the safer way to implement this without crashing, even if the dynamically created vector array is large in number and it will be so helpful if you provide an adequate example or link with the needed return types.
Ok, here is a sample. I fill a vector with a few pointers-to-ints. Then I delete them one by one, and clear the vector at last. If I woudnt manually call delete operator on each element prior to Vector.clear(), there would be leaked memory.
std::vector<int*> Vector;
for (int i = 0; i < 10; i++)
Vector.push_back(new int(i));
std::vector<int*>::const_iterator It;
for (It = Vector.begin(); It != Vector.end(); It++)
{
int* n = *It;
if (n) delete n;
}
Vector.clear();

removing things from a pointer vector

I have a vector of pointers like so:
vector<Item*> items;
I want to clear it. I've tried:
for (unsigned int i = 0; i < items.size(); i++)
delete items.at(i);
items.clear();
,
while (!items.empty())
{
delete items.back();
items.pop_back();
}
,
while (!items.empty())
{
delete items.at(0);
items.erase(items.begin());
}
, and
while (!items.empty())
delete items.at(0);
Every single one of these blows up for some reason or another, including deletion of already deleted objects and out of range vector iterators.
What do I do? I want to be able to reuse that same vector and add more Item pointers into it later. Just using delete without clearing still leaves junk pointers in there, right?
EDIT: Okay, I've switched to shared_ptrs. Now I have
vector<shared_ptr<Item> > items;
Yet, when I do items.clear(); , I get the error "vector iterators incompatible". What am I still doing wrong?
I ran a test with all your ways of deleting stuff, and one of them simply doesn't work. See the code below for the comments on them.
To answer your question "what do I do," here is what I do when I seg-fault on a delete:
1) Make sure the memory is mine (do I know where the corresponding new is)?
2) Make sure I didn't delete the memory already (if I did, even if it WAS mine, it isn't now).
3) If you're pretty sure your seg-fault is caused by a single section of your code, break it out into a small test case in another project (kind of like you did in your question). Then play with it. If you had run your code examples up top in a small project you would have seen the seg-fault on the last one, and you would have noted the deletes worked in every other case. Breaking the code down like this would have let you know that you need to trace how you are storing these in your vector to see where you are losing ownership of them (via delete, or passing them to something that deletes them, etc...).
A side note: as others are saying, if you can use smart pointers do so, they will take care of the memory management for you. However, please continue your study here and understand how to use pointers that are dumb. There are times when you can not import boost, or have QT do your memory management for you. Also, there are times when you MUST store pointers in a container so don't be afraid to do that either (IE: QT developers STRONGLY suggest using pointers to store widgets instead of references or anything of the sort).
#include <vector>
using namespace std;
class Item
{
public:
int a;
};
int main()
{
vector<Item *> data;
for(int x = 0; x < 100; x++)
{
data.push_back(new Item());
}
//worked for me, and makes sense
for(int x = 0; x < 100; x++)
{
delete data.at(x);
}
data.clear();
for(int x = 0; x < 100; x++)
{
data.push_back(new Item());
}
//worked for me, and makes sense
while (!data.empty())
{
delete data.back();
data.pop_back();
}
data.clear();
for(int x = 0; x < 100; x++)
{
data.push_back(new Item());
}
// //worked for me, and makes sense
while (!data.empty())
{
delete data.at(0);
data.erase(data.begin());
}
for(int x = 0; x < 100; x++)
{
data.push_back(new Item());
}
// //This one fails, you are always trying to delete the 0th position in
// //data while never removing an element (you are trying to delete deleted memory)
// while (!data.empty())
// {
// delete data.at(0);
// }
return 0;
}
Either use a vector of smart pointers like this:
vector<shared_ptr<Item> > myVect;
Or use the Pointer Containers library in boost.
There may be a way to do this and re-use things, but it seems error-prone and a lot more work, especially considering Pointer Containers in boost is a header-only library.
use boost::shared_ptr<Item> and they will be deleted when the vector is cleared, or the element is deleted.
What do I do?
Don't maintain a vector of pointers. Really, it's almost always a mistake and you are fighting against the design of the vector (RAII) which takes care of memory management for you. You now have to call delete on every pointer.
Do you really need a vector of pointers? If you really do (not just think you do, but it is actually a requirement for one reason or another), then use smart pointers.
The vector will dynamically allocate memory for you, just use it as it was intended to be used.
It sounds as if you have the same pointer(s) repeated in your vector. To be sure you are only deleting them once just transfer them to a std::set and delete them there. For example,
std::set<Item*> s( items.begin(), items.end() );
items.clear();
while ( !s.empty() )
{
delete *s.begin();
s.erase( s.begin() );
}
Well, I did it. After a lot of time, a lot of aspirin, and a lot of lost hair, I finally figured out what the problem was. Turns out that I was calling a particular destructor earlier that contained the class which contained this vector of pointers. I had no idea that just calling a destructor would cause it to wipe all static data members. I hate c++ sometimes.

Filling an array of pointers, deleting when exiting

In C++, Lets say I'm creating an array of pointers and each element should point to a data type MyType. I want to fill this array in a function fillArPtr(MyType *arPtr[]). Lets also say I can create MyType objects with a function createObject(int x). It works the following way:
MyType *arptr[10]; // Before there was a mistake, it was written: "int *arptr[10]"
void fillArPtr(MyType *arptr[])
{
for (int i = 0; i < 10; i++)
{
MyType myObject = createObject(i);
arptr[i] = new MyType(myobject);
}
}
Is it the best way to do it? In this program how should I use delete to delete objects created by "new" (or should I use delete at all?)
Since you asked "What is the best way", let me go out on a limb here and suggest a more C++-like alternative. Since your createObject is already returning objects by value, the following should work:
#include <vector>
std::vector<MyType> fillArray()
{
std::vector<MyType> res;
for (size_t i = 0; i != 10; ++i)
res.push_back(createObject(i));
return res;
}
Now you don't need to do any memory management at all, as allocation and clean-up is done by the vector class. Use it like this:
std::vector<MyType> myArr = fillArray();
someOtherFunction(myArr[2]); // etc.
someLegacyFunction(&myArr[4]); // suppose it's "void someLegacyFunction(MyType*)"
Do say if you have a genuine requirement for manual memory management and for pointers, though, but preferably with a usage example.
Your method places the array of pointers on the stack, which is fine. Just thought I'd point out that it's also possible to store your array of pointers on the heap like so. Youd do this if you want your array to persist beyond the current scope
MyType **arptr = new MyType[10];
void fillArPtr(MyType *arptr[])
{
for (int i = 0; i < 10; i++)
{
MyType myObject = createObject(i);
arptr[i] = new MyType(myobject);
}
}
If you do this, don't forget to delete the array itself from the heap
for ( int i = 0 ; i < 10 ; i++ ) {
delete arptr[i];
}
delete [] arptr;
If you're going to use vector, and you know the size of the array beforehand, you should pre-size the array. You'll get much better performance.
vector<MyType*> arr(10);
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
I suggest you look into boost shared_ptr (also in TR1 library)
Much better already:
std::vector<MyType*> vec;
for (int i=0; i<10; i++)
vec.push_back(new MyType(createObject(i));
// do stuff
// cleanup:
while (!vec.empty())
{
delete (vec.back());
vec.pop_back();
}
Shooting for the stars:
typedef boost::shared_ptr<MyType> ptr_t;
std::vector<ptr_t> vec;
for (int i=0; i<10; i++)
vec.push_back(ptr_t(new MyType(createObject(i)));
You would basically go through each element of the array and call delete on it, then set the element to 0 or null.
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
Another way to do this is with an std::vector.
Use an array of auto_ptrs if you don't have to return the array anywhere. As long as you don't make copies of the auto_ptrs, they won't change ownership and they will deallocate their resources upon exiting of the function since its RAII based. It's also part of the standard already, so don't need boost to use it :) They're not useful in most places but this sounds like a good one.
You can delete the allocated objects using delete objPtr. In your case,
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
The rule of thumb to remember is, if you allocate an object using new, you should delete it. If you allocate an array of objects using new[N], then you must delete[] it.
Instead of sticking pointers into a raw array, have a look at std::array or std::vector. If you also use a smart pointer, like std::unique_ptr to hold the objects within an std::array you don't need to worry about deleting them.
typedef std::array<std::unique_ptr<MyType>, 10> MyTypeArray;
MyTypeArray arptr;
for( MyTypeArray::iterator it = arptr.begin(), int i = 0; it != arptr.end(); ++it ) {
it->reset( new MyType( createObject(i++) ) );
}
You don't need to worry about deleting those when you're done using them.
Is the createObject(int x) function using new to create objects and returning a pointer to this?. In that case, you need to delete that as well because in this statement
new MyType( createObject(i++) )
you're making a copy of the object returned by createObject, but the original is then leaked. If you change createObject also to return an std::unique_ptr<MyType> instead of a raw pointer, you can prevent the leak.
If createObject is creating objects on the stack and returning them by value, the above should work correctly.
If createObject is not using new to create objects, but is creating them on the stack and returning pointers to these, your program is not going to work as you want it to, because the stack object will be destroyed when createObject exits.

creating an array of object pointers C++

I want to create an array that holds pointers to many object, but I don't know in advance the number of objects I'll hold, which means that I need to dynamically allocate memory for the array. I have thought of the next code:
ants = new *Ant[num_ants];
for (i=1;i<num_ants+1;i++)
{
ants[i-1] = new Ant();
}
where ants is defined as Ant **ants; and Ant is a class.
Will it work?
Will it work?
Yes.
However, if possible, you should use a vector:
#include <vector>
std::vector<Ant*> ants;
for (int i = 0; i < num_ants; ++i) {
ants.push_back(new Ant());
}
If you have to use a dynamically allocated array then I would prefer this syntax:
typedef Ant* AntPtr;
AntPtr * ants = new AntPtr[num_ants];
for (int i = 0; i < num_ants; ++i) {
ants[i] = new Ant();
}
But forget all that. The code still isn't any good since it requires manual memory management. To fix that you could to change your code to:
std::vector<std::unique_ptr<Ant>> ants;
for (auto i = 0; i != num_ants; ++i) {
ants.push_back(std::make_unique<Ant>());
}
And best of all would be simply this:
std::vector<Ant> ants(num_ants);
std::vector<Ant> ants(num_ants);
ants.resize(new_num_ants);
Yes that's the general idea. However, there are alternatives. Are you sure you need an array of pointers? An array of objects of class Ant may be sufficient. The you would only need to allocate the array:
Ant *ants = new Ant[num_ants];
In general, you should prefer using std::vector to using an array. A vector can grow as needed, and it will handle the memory management for you.
In the code you have posted, you would have to delete each element of ants in a loop, and then delete the array itself, delete [] ant. Keep in mind the difference between delete and delete [].
One more point, since array indices in C++ are 0-based, the following convention is used to iterate over the elements:
for (i=0; i<num_ants; i++)
{
ants[i] = new Ant();
}
This makes code much more readable.
Do you really need to hold pointers to the items? If you can use objects by value, a far simpler approach is to use a vector: std::vector<Ant> ants(num_ants);. Then not only do you not have to write looping, but you don't have to worry about memory leaks from raw pointers and other object management items.
If you need object pointers to say satisfy an API you can still use vector for the outer container and allocate the objects manually.
struct CreateAnt
{
Ant* operator()() const { return new Ant; }
};
std::vector<Ant*> ants(num_ants); // Create vector with null pointers.
std::generate(ants.begin(), ants.end(), CreateAnt());
std::vector<Ant*> ants( num_ants );
for ( int i = 0; i != num_ants; ++ i ) {
ants[i] = new Ant;
}
Or if you don't know how many in advance:
std::vector<Ant*> ants;
while ( moreAntsNeeded() ) {
ants.push_back( new Ant );
}
On the other hand, I think you need to ask yourself whether
Ant is an entity type or a value. If it's a value, you'll
probably want to skip the pointers and the dynamic allocation;
if it's an entity type, you'll have to consider the lifetime of
the object, and when and where it will be deleted.