How to delete memory of a pointer to pointer in C++ - c++

Using Valgrind, I see that I have a problem while deleting the memory in the following function:
Obj1 Obj1::operator*(const Obj1& param) const {
int n = param.GetSize(2);
Obj2** s = new Obj2*[n];
for( int i = 0; i < n; ++i) {
s[i] = new Obj2(*this*param.GetColumn(i+1));
}
Obj1 res = foo(s,n);
for(int i=n-1;i>-1;i--) {
s[i]->~Obj2();
}
delete[] s;
return res;
Valgrind tells me that the leak comes from the line
s[i] = new Obj2(*this*param.GetColumn(i+1));
I'm not pretty sure if the problem is when I try to free the memory. Can anyone tell me how to fix this problem?

Here:
s[i] = new Obj2(*this*param.GetColumn(i+1));
you create a dynamic object and assign s[i]to point to it.
In order to delete it, you do this:
delete s[i];
Unless you do that, the allocation will leak.
You must repeat that in a loop for every i just like you repeated the allocations. You of course have to do this before you delete s itself.
s[i]->~Obj2();
Don't do that. Calling the destructor is not appropriate here. delete will call the destructor.
P.S. Don't use raw owning pointers. Use containers or smart pointers instead. std::vector is a standard containers for dynamic arrays.
P.P.S. You should avoid unnecessary dynamic allocation. Your example doesn't demonstrate any need to allocate the pointed objects dynamically. So, in this case you should probably use std::vector<Obj2>.

Related

Trying to deallocate a dynamic array of std::forward_list pointers (C++)

I'm trying to deallocate a dynamically allocated array of pointers to forward lists that was created with something like:
deck = new forward_list<T>*[numDecks];
for (int i = 0; i < numDecks; i++) {
deck[i] = new forward_list<T>;
}
numberOfDecks = numDecks;
I tried to iterate and delete the decks like this:
for (int i = 0; i < numDecks; i++) {
delete[] deck[i];
numberofDecks--;
}
delete[] deck;
But I got a read access violation. In fact, even if I just write:
delete[] deck[0];
I still get a read access violation. I've been playing around with this for quite some time and haven't been able to get it to work. I'm attaching a screenshot of the error (it appears in the forward_list file.
Thank you.
delete[] is for deleteing something that was allocated via new []. When you allocated something via new you need to delete it via delete.
There is no apparent reason for any manual dynamic allocations in your code. The std::forward_list already manages the memory of its elements. Storing pointers in the list has no advantage unless you need a level of indirection for some reason. And if you need it you should use smart pointers not raw ones. Also allocating the std::forward_list itself dynamically is most likely not needed (and again: use smart pointer if you do).
Your code has undefined behavior, as you are creating the std::forward_list objects using new but then destroying them with delete[] instead of delete. You need to change this:
delete[] deck[i];
To this:
delete deck[i];
new/delete are for single objects, and new[]/delete[] are for arrays. They must be matched up properly.
A better option is to use std::vector<std::forward_list> instead of std::forward_list*[], and let the vector handle the memory for you.

Dynamic allocation with C++'s "placement new"

The question: How to use "placement new" for creating an array with dynamic size? or more specifically, how to allocate memory for array elements from a pre-allocated memory.
I am using the following code:
void* void_array = malloc(sizeof(Int));
Int* final_array = new(void_array) Int;
This guarantees that the final_array* (the array pointer) is allocated from the place that is reserved by void_array*. But what about the final_array elements? I want them to be allocated from a pre-allocated memory as well.
P.S: I have to say that I'm using some API that gives me some controls over a tile architecture. There is a function that works exactly like malloc, but also have other features, e.g. lets you control the properties of the allocated memory. So, what i basically need to do, is to use that malloc-like function to allocate memory with my desired properties (e.g. from which memory bank, to be cached where and etc.)
First off, let's make sure we all agree on the separation of memory allocation and object construction. With that in mind, let's assume we have enough memory for an array of objects:
void * mem = std::malloc(sizeof(Foo) * N);
Now, you cannot use placement array-new, because it is broken. The correct thing to do is construct each element separately:
for (std::size_t i = 0; i != N; ++i)
{
new (static_cast<Foo*>(mem) + i) Foo;
}
(The cast is only needed for the pointer arithmetic. The actual pointer required by placement-new is just a void pointer.)
This is exactly how the standard library containers work, by the way, and how the standard library allocators are designed. The point is that you already know the number of elments, because you used it in the initial memory allocation. Therefore, you have no need for the magic provided by C++ array-new, which is all about storing the array size somewhere and calling constructors and destructors.
Destruction works in reverse:
for (std::size_t i = 0; i != N; ++i)
{
(static_cast<Foo*>(mem) + i)->~Foo();
}
std::free(mem);
One more thing you must know about, though: Exception safety. The above code is in fact not correct unless Foo has a no-throwing constructor. To code it correctly, you must also store an unwind location:
std::size_t cur = 0;
try
{
for (std::size_t i = 0; i != N; ++i, ++cur)
{
new (static_cast<Foo*>(mem) + i) Foo;
}
}
catch (...)
{
for (std::size_t i = 0; i != cur; ++i)
{
(static_cast<Foo*>(mem) + i)->~Foo();
}
throw;
}
Instead of using a custom malloc, you should overwrite operator new() and use it. This is not operator new; there is a function actually called operator new(), confusing as it may seem, which is the function used by the normal (non-placement) operator new in order to get raw memory upon which to construct objects. Of course, you only need to overwrite it if you need special memory management; otherwise the default version works fine.
The way to use it is as follows, asuming your array size will be size:
Int* final_array = static_cast<Int*>(size == 0 ? 0 : operator new(sizeof(Int) * size));
Then you can construct and destroy each element independently. For instance, for element n:
// Create
new(final_array + n) Int; // use whatever constructor you want
// Destroy
(final_array + n)->~Int();

C++ array of pointer memory leaks

In my class I have a dynamically allocated array of pointers. My declaration:
array = new Elem* [size];
for (int i = 0; i < size; i++) {
array[i] = NULL;
}
So there is an array of pointers, where each pointer points to a simple Elem struct.
The main question is, how should I properly deallocate the array. If I use only:
for (int i = 0; i < size; i++) {
delete array[i];
}
Valgrind reports 1 not-freed block, which is traced to the line where 'array = new Elem* [size];' states.
On the other hand if I add to the previous code:
delete array;
Which I thought is correct, valgrind reports 0 not-freed blocks, which is perfect, BUT it reports
Mismatched free() / delete / delete []
exactly on the line where 'delete array;' is. I tried 'delete []array' too, but that's just "1 not-freed blocks" too then! If somebody could explain me the proper way it would be much appreciated.
EDIT:
So using:
for (int i = 0; i < size; i++) {
delete array[i];
}
delete[] array;
is working probably fine. It is working in one of my classes (I have two similar) the other still reports some small leak. I would think it's just a minor bug somewhere, but valgrind still points to the line where
array = new Elem* [size];
stands.
EDIT2:
I solved this as well, thank you for your exhausting contribution!!
You need:
delete [] array;
Because it's an array.
I just noticed your note that you tried this too - it's the proper thing to do so I don't know why you'd still be getting an error.
Edit: This deserves a more thorough explanation.
When you create a pointer using new, the pointer may be to a single element or an array of elements depending on the syntax you use. But the pointer type is the same in both cases! The compiler relies on you to know what the pointer points to and treat it accordingly.
Elem ** single = new Elem*; // pointer to one pointer
single[0] = new Elem; // OK
single[1] = new Elem; // runtime error, but not compile time
Elem ** array = new Elem* [2]; // pointer to array of pointers
array[0] = new Elem; // OK
array[1] = new Elem; // OK
When you delete a pointer, the destructor is called for the object it points to or for each element of the array. But since the pointer type is the same in each case, the compiler relies on you to give it the proper syntax so it knows what to do.
delete single;
delete [] array;
In your case the elements of the array are pointers also, and pointers don't have destructors. That means those pointers won't be deleted and will become memory leaks if you don't delete them first. You were correct to have a loop to delete them individually before the final delete.
You should free everything in the array (if dynamically allocated) and then free the array itself.
for (int i = 0; i < size; i++) { // only free inside if dynamically allocated - not if just storing pointers
delete array[i];
}
delete[] array; // necesarry
The syntax for deleting an array is like this:
delete[] array;
Your for loop to delete the objects pointed to by the elements of the array is fine. The deletion of the array itself is the only problem. You need both the for loop and then the delete[] to dispose of the array itself.
for (int i = 0; i < size; i++) {
delete array[i];
}
delete[] array;
I suspect that you have tried using the for loop, or the delete[], but not both together. And if when you do that you still have leaks or errors, then you would need to show us the code that allocates the pointers that are elements of the array.
Using std::vector<> instead of an array would mean that you could stop worrying about these nitty gritty details and move to higher level of abstraction.
In this case, you need both.
for (int i = 0; i < size; i++) {
delete array[i];
}
delete[] array;
You call delete exactly once for each time you called new.
Note that although you need to call delete[] array here (because you allocated it with new[]), the delete[] operator does not call the destructors on the objects pointed to by elements of the array. This is because the delete[] operator calls destructors on objects in the array, and your array contains pointers but not objects. Pointers do not themselves have destructors.

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.

Deleting an Array of Pointers - Am I doing it right?

I feel a little stupid for making a question about the deletion of pointers but I need to make sure I'm deleting in the correct way as I'm currently going through the debugging process of my program.
Basically I have a few arrays of pointers which are defined in my header file as follows:
AsteroidView *_asteroidView[16];
In a for loop I then initialise them:
for(int i = 0; i < 16; i++)
{
_asteroidView[i] = new AsteroidView();
}
Ok, so far so good, everything works fine.
When I eventually need to delete these in the destructor I use this code:
for(int i = 0; i < 16; i++)
{
delete _asteroidView[i];
}
Is this all I need to do? I feel like it is, but I'm worried about getting memory leaks.
Out of interest...
Is there much of a difference between an Array of Points to Objects compared with an Array of Objects?
This is correct. However, you may want to consider using Boost.PointerContainer, and save you hassle the hassle of manual resource management:
boost::ptr_vector<AsteroidView> _asteroidView;
for(int i = 0; i < 16; i++)
{
_asteroidView.push_back(new AsteroidView());
}
You do not have to manage the deletion, the container does that for you. This technique is called RAII, and you should learn about it if you want to have fun using C++ :)
About your edit: There are several difference, but I guess the most important are these:
An array of pointers can contain objects of different types, if these are subclasses of the array type.
An array of objects does not need any deletion, all objects are destroyed when the array is destroyed.
It's absolutely fine.
The rule of thumb is: match each call to new with an appropriate call to delete (and each call to new[] with a call to delete[])
Is this all I need to do? I feel like it is, but I'm worried about getting memory leaks.
Yes. The program is deallocating resources correctly. No memory leaks :)
If you are comfortable with using std::vector( infact it is easy ), it does the deallocation process when it goes out of scope. However, the type should be of -
std::vector<AsteroidView>
Given a class:
// this class has hidden data and no methods other than the constructor/destructor
// obviously it's not ready for prime time
class Foo {
int* bar_[16];
public:
Foo()
{
for (unsigned int i = 0; i < 16; ++i)
bar_[i] = new int;
}
~Foo()
{
for (unsigned int i= 0; i < 16; ++i)
delete bar_[i];
}
};
You won't leak memory if the constructor completes correctly. However, if new fails fails in the constructor (new throws a std::bad_alloc if you're out of memory), then the destructor is not run, and you will have a memory leak. If that bothers you, you will have to make the constructor exception safe (say, add a try ... catch block around the constructor, use RAII). Personally, I would just use the Boost Pointer Container if the elements in the array must be pointers, and a std::vector if not.