Cleaning up after a dynamically assigned, multi-dimensional array - c++

So, I have dynamically assigned memory to a 2D array:
int **paMatrix = new int*[r];
for(int i=0; i<r; i++)
paMatrix[i] = new int[c];
Assume that my code has already defined r and c. Now I want to free the memory again. If paMatrix was single-indexed, the delete[] paMatrix; would be enough. Is it also enough in this case, or do I have to write
for(int i=0; i<r; i++)
delete[] paMatrix[i];
delete[] paMatrix;
In case I need to call delete once for each new statement, is there a way to rewrite my code so that I only need a single delete statement?

In general, you need to match every new with a delete so if, as here, you're juggling a whole array of raw pointers, you will indeed need to delete each in turn.
This can be a serious hassle if the code between new and delete isn't straightforward, and almost impossible to ensure if it might throw exceptions. For that reason, you should always use RAII types such as containers and smart pointers to manage dynamic resources. In this case, vector<vector<int>> might be an appropriate choice.
I guess the real question is "What does delete and delete[] really do behind the scene?"
If the object type has a non-trivial destructor, it calls that destructor on each object before deallocating the memory. Thus RAII types will automatically release whatever resource they manage through their destructor; but raw pointers don't have destructors, so deleting them will not free any memory that they point to.

As said, in c++ one rarely has more then one indirection through pointers. In a matter of fact, in c++ pointers are avoided whenever possible.
In case I need to call delete once for each new statement, is there a way to rewrite my code so that I only need a single delete statement?
One way would be :
int *paMatrix = new int[r*c];
but then you need to play with indexes.
Another solution (without pointers) without even one delete statement is to use std::vector :
std::vector< std::vector< int > > paMatrix( r, std::vector< int >( c, 0 ) );

You need
for(int i=0; i<r; i++)
delete[] paMatrix[i];
delete[] paMatrix;
There's no way around, except smart pointers etc.

As described in the other answers here, you need to match calls to new with calls to delete.
However if you were willing to change your conception of a 2d array, you can simplify it considerably. For example if it truly a matrix of r x c size you could allocate it as a single array of r*c in size:
int* paMatrix = new int[r*c];
Then you would be able to delete it in a single step.
The tradeoff would be having to index the array using something like paArray[x+c*y] instead of the more natural paArray[x][y].

Related

C++ (not C++11) Best way to release array in very large methods

I have to modify a very large method with many possible execution flows. The modification involves to allocate a char array in the heap using new. I want to be sure that this array is released properly, but I want to avoid the need of do the delete[] in all the possible execution flows. In addition, I want to make something "cleaner" for this purpose to avoid future bugs.
I have thought to alloc the array with new and then wrap it into a local std::vector (but keeping the reference to the raw pointer, since the method uses this reference intensively) and let the wrapper delete the raw pointer when it is out of scope.
Here I attach an example. The purpose of this example is to show the kind of operations that are peformed with the raw pointer.
char *rawPtr = new char[1024];
std::vector wrapper(rawPtr, rawPtr + 1024); // <= Does it assure that rawPtr will be released properly?
...
for(int i = 0; i < 1024; i++)
rawPtr[i] = ...;
rawPtr += sizeof(...);
...
rawPtr -= ...;
if(...)
return ...;
return ...;
So, my question is if I can be sure that the rawPtr will be released properly regardless program failures, exceptions, incoming return statements etc.
PD.: I cannot use C++11, the most similar thing I have to a smart pointer is auto_ptr and this uses delete, not delete[].
You can create vector<char> of length 1024 and then use pointer to its first element as rawPtr. It will be no need to call new and delete[] then.
std::vector doesn't have a move constructor for newed pointers. What happens, is that a copy is made for std::vector's use. So you will still need to delete.

Freeing last element of a dynamic array

I have
int * array=new int[2];
and I would like to free the memory of the last element, thus reducing the allocated memory to only 1 element. I tried to call
delete array+1;
but it gives error
*** glibc detected *** skuska:
free(): invalid pointer: 0x000000000065a020 *
Can this be done in C++03 without explicit reallocation?
Note: If I wanted to use a class instead a primitive datatype (like int), how can I free the memory so that the destructor of the class is called too?
Note2: I am trying to implement vector::pop_back
Don't use new[] expression for this. That's not how vector works. What you do is allocate a chunk of raw memory. You could use malloc for this, or you could use operator new, which is different from the new expression. This is essentially what the reserve() member function of std::vector does, assuming you've used the default allocator. It doesn't create any actual objects the way the new[] expression does.
When you want to construct an element, you use placement new, passing it a location somewhere in the raw memory you've allocated. When you want to destoy an element, you call its destructor directly. When you are done, instead of using the delete[] expression, you use operator delete if you used operator new, or you use free() if you used malloc.
Here's an example creating 10 objects, and destoying them in reverse order. I could destroy them in any order, but this is how you would do it in a vector implementation.
int main()
{
void * storage = malloc(sizeof(MyClass) * 10);
for (int i=0; i<10; ++i)
{
// this is placement new
new ((MyClass*)storage + i) MyClass;
}
for (int i=9; i>=0; --i)
{
// calling the destructor directly
((MyClass*)storage + i)->~MyClass();
}
free(storage);
}
pop_back would be implemented by simply calling the destructor of the last element, and decrementing the size member variable by 1. It wouldn't, shouldn't (and couldn't, without making a bunch of unnecessary copies) free any memory.
There is no such option. Only way to resize array is allocate new array with size old_size - 1, copy content of old array and then delete old array.
If you want free object memory why not create array of pointers?
MyClass **arr = new MyClass*[size];
for(int i = 0; i < size; i++)
arr[i] = new MyClass;
// ...
delete arr[size-1];
std::vector::pop_back doesn't reallocate anything — it simply updates the internal variable determining data size, reducing it by one. The old last element is still there in memory; the vector simply doesn't let you access it through its public API. *
This, as well as growing re-allocation being non-linear, is the basis of why std::vector::capacity() is not equivalent to std::vector::size().
So, if you're really trying to re-invent std::vector for whatever reason, the answer to your question about re-allocation is don't.
* Actually for non-primitive data types it's a little more complex, since such elements are semantically destroyed even though their memory will not be freed.
Since you are using C++03, you have access to the std::vector data type. Use that and it's one call:
#include <vector>
//...
std::vector<int> ary(3);
//...
ary.erase(ary.begin() + (ary.size() - 1));
or
#include <vector>
//...
std::vector<int> ary(3);
//...
ary.pop_back();
EDIT:
Why are you trying to re-invent the wheel? Just use vector::pop_back.
Anyway, the destructor is called on contained data types ONLY if the contained data type IS NOT a pointer. If it IS a pointer you must manually call delete on the object you want to delete, set it to nullptr or NULL (because attempting to call delete on a previously deleted object is bad, calling delete on a null pointer is a non-op), then call erase.

Class size instantiated in a sub-function, i.e. is this a good time to use new?

I want to create a vector of data, but I want to both set it's size and fill its elements in a sub-function. Is this an appropriate time to use the new operator? Is there a better way to do it? It seems like an appropriate time, but I'm hesitant because of Why should C++ programmers minimize use of 'new'?
int main()
{
vector<double> *array1;
vector<double> *array2;
OtherArgs otherArgs;
FillArrays(array1,array2,otherArgs);
//Do other stuff
delete array1;
delete array2;
}
void FillArrays(vector<double> *&array1, vector<double> *&array2, OtherArgs &otherArgs)
{
int size=GetSize(otherArgs);
array1 = new vector<double>(size);
array2 = new vector<double>(size);
//Other code to fill the arrays
}
Thank you
Here are a couple of reasons why the original sample is troublesome
The code leaks memory in the face of an exception because the delete calls aren't protected
If FillArrays is passed a non-NULL vectory<double> value it will leak memory because it didn't delete the previous value. It couldn't reliably call delete even if it wanted to because the value may have been stack allocated.
The easiest way to do this is to just declare the values on the stack and pass them by reference that way.
int main()
{
vector<double> array1;
vector<double> array2;
OtherArgs otherArgs;
FillArrays(array1,array2,otherArgs);
//Do other stuff
}
void FillArrays(vector<double> &array1, vector<double> &array2, OtherArgs &otherArgs)
{
int size=GetSize(otherArgs);
//Other code to fill the arrays
}
The vector<T> will initialize themselves to an empty list when declared in this manner. The FillArrays method can then populate them as necessary.
No, this is a specifically bad use of new.
If you must use new and delete1, use them as bookends. The delete expression should be in a logically consistent context with the new expression.
So, if you new in a c-tor, you should delete in the d-tor. If you new in an allocation function, you should delete in a deallocation function. The two calls should be arranged in an way that makes it obvious that one starts an operation and the other finishes it.
This implies that the call to new and delete should exist in the same layer in a functional or object hierarchy. Specifically, new and delete should be seen as implementation details, and not as part of the API contract.2
In your case, the new and delete are in entirely distinct contexts. new is inside the implementation, while delete is called for in the client. This will lead to programming errors.
Beyond that, the non-new version of your code (creating empty vectors in main, and passing them by reference) is simpler, easier to read, and more exception-friendly than the new version.
No, this is not a good example of when to use new. It is, however, an excellent example of when not to.
1 You hardly ever need to use new and delete. If you need dynamic allocation, just let containers keep copies of your objects.
2 std::shared_ptr, et al, violate this rule -- the new and delete are specifically part of the contract. This is probably OK, since pointer manipulation is their reason for existence. But SO has seen its share of bugs about storing a non-new pointer in shared_ptr.

How to delete a vector without importing any library

vector<char*> x;
I have many vectors in my code. However, I need to delete them to minimize memory usage. I know there is a solution like using a "shared_array" but I am not permitted to import any other library. Is there any good solution to prevent memory leak after using vectors?
In your code snippet, you are using a vector of char pointers. I assume that those pointers are allocated via new, and they need to be freed via delete. If the vector goes out of scope, it will be freed, but all those char arrays won't get freed. You need to free them manually.
An alternative would be to use std::string, specifically vector<std::string>. In this way, when the vector goes out of scope, all the strings will be automatically deleted.
C++11 has support for smart pointer objects, such as shared_ptr, so you don't have to use Boost (or anything else).
As johnathon said, you can then just wrap the char * with a smart pointer et voilà, you don't have to worry about it anymore.
std::vector<std::unique_ptr<char*>> x;
or
std::vector<std::shared_ptr<char*>> x;
When the element is removed from the vector in either way (.delete(), .erase(), ...) or simply when vector is destroyed, you buffers will be freed.
If your STL implementation or compiler does not support this C++11 feature yet, you can also roll your own smart pointer type, it shouldn't be too hard. See for example this tutorial.
You may use
//Create
vector<char*>* _vec = new vector<char*>(5);
//Fill with something
for(unsigned int i=0; i<_vec->size(); ++i)
(*_vec)[i] = new char[100];
....
//Delete
for(unsigned int i=0; i<_vec->size(); ++i)
delete[] (*_vec)[i]; //Deleting array of char
delete _vec; //but not delete[] as we deleting only one instance of vector

C++ deleting a pointer to a pointer

So I have a pointer to an array of pointers. If I delete it like this:
delete [] PointerToPointers;
Will that delete all the pointed to pointers as well? If not, do I have to loop over all of the pointers and delete them as well, or is there an easier way to do it? My google-fu doesn't seem to give me any good answers to this question.
(And yeah, I know I need to use a vector. This is one of those "catch up on C++" type assignments in school.)
Yes you have to loop over the pointers, deleting individually.
Reason: What if other code had pointers to the objects in your array? The C++ compiler doesn't know if that's true or not, so you have to be explicit.
For an "easier way," two suggestions: (1) Make a subroutine for this purpose so at least you won't have to write the code more than once. (2) Use the "smart pointer" design paradigm where you hold an array of objects with reference-counters, then the objects are deleted when the objects are no longer referenced by any code.
I agree with Jason Cohen though we can be a bit clearer on the reason for needing to delete your pointers with the loop. For every "new" or dynamic memory allocation there needs to be a "delete" a memory de-allocation. Some times the "delete" can be hidden, as with smartpointers but it is still there.
int main()
{
int *pI = new int;
int *pArr = new int[10];
so far in the code we have allocated two chunks of dynamic memory. The first is just a general int the second is an array of ints.
delete pI;
delete [] pArr;
these delete statements clear the memory that was allocated by the "new"s
int ppArr = new int *[10];
for( int indx = 0; indx < 10; ++indx )
{
ppArr[indx] = new int;
}
This bit of code is doing both of the previous allocations. First we are creating space for our int in a dynamic array. We then need to loop through and allocate an int for each spot in the array.
for( int indx = 0; indx < 10; ++indx )
{
delete ppArr[indx];
}
delete [] ppArr;
Note the order that I allocated this memory and then that I de-allocated it in the reverse order. This is because if we were to do the delete [] ppArr; first we would lose the array that tells us what our other pointers are. That chunk or memory would be given back to the system and so can no longer be reliably read.
int a=0;
int b=1;
int c=2;
ppArr = new int *[3];
ppArr[0] = &a;
ppArr[1] = &b;
ppArr[2] = &c;
This I think should be mentioned as well. Just because you are working with pointers does not mean that the memory those pointers point to was dynamically allocated. That is to say just because you have a pointer doesn't mean it necessarily needs to be delete. The array I created here is dynamically allocated but the pointers point to local instances of ints When we delete this we only need to delete the array.
delete [] ppArr;
return 0;
}
In the end dynamically allocated memory can be tricky and anyway you can wrap it up safely like in a smart pointer or by using stl containers rather then your own can make your life much more pleasant.
See boost pointer container for a container that does the automatic deletion of contained pointers for you, while maintaining a syntax very close to ordinary STL containers.
Pointers are pretty much just memory references and not spiffy little self-cleaning .net objects. Creating proper destructors for each class will make the deletion a little cleaner than massive loops throughout the code.
Let's take a (pseudocoded) real world example .Imagine that you had a class like this:
class Street
{
public:
Street();
~Street();
private:
int HouseNumbers_[];
}
typedef *Street StreetSign;
If you have an array of street signs, and you delete your array of streetsigns, that doesn't mean that you automatically delete the sreets. They re still there, bricks and mortar, they just don't have those signs pointing to them any more. You have got rid of those specific instances of pointers to the streets.
An array of pointers is (conceptually) a bit like an array of integers, it's an array of numbers representing the memory locations of various objects. It isn't the objects themselves.
If you delete[] the array of pointers, all you have done is delete an array of integers.
I think you're going to have to loop over I'm afraid.
I don't know why this was answered so confusingly long.
If you delete the array of pointers, you will free
the memory used for an array of usually ints.
a pointer to an object is an integer containing the adress.
You deleted a bunch of adresses, but no objects.
delete does not care about the content of a memory space,
it calls a destructor(s) and marks the mem as free.
It does not care that it just deleted a bunch of adresses
of objects, it merely sees ints.
That's why you have to cycle through the array first! and call delete
on every element, then you can delete the storage of the array itself.
Well, now my answer got somewhat long... .... strange... ;)
Edit:
Jason's answer is not wrong, it just fails to hit the spot. Neither
the compiler nor anything else in c(++) cares about you deleting stuff that is elsewhere
pointed to. You can just do it. Other program parts trying to use the deleted objects
will segfault on you. But no one will hinder you.
Neither will it be a problem to destroy an array of pointers to objects, when the objects
are referenced elsewhere.