I've a 3x3 2D dynamic array allocated as below:
int** matrix = new int* [3];
matrix[0] = new int [3*3];
for (int i = 1; i < 3; ++i)
matrix[i] = matrix[i-1] + 3;
How should I deallocate it? Is this correct:
delete [] matrix;
delete [] matrix[0];
Or should I also delete matrix[1], [2]
The way you have it, you should :
delete [] matrix[0];
delete [] matrix;
But this is a very unconventional way of allocating a dynamic 2D array. Normally you allocate an array of pointers, and then you allocate an array of your actual type for every row (column).
// allocate
int **matrix = new int*[3];
for(int i = 0; i < 3; ++i)
matrix[i] = new int[3];
// deallocate
for(int i = 0; i < 3; ++i)
delete [] matrix[i];
delete [] matrix;
You'll need one delete for each new, in reverse order of the new's.
The code:
delete [] matrix;
delete [] matrix[0];
is obviously wrong, as you use matrix after you delete it.
delete [] matrix[0];
delete [] matrix;
is correct, but I can't vouch that the code as whole does something sensible.
Note that you should not delete matrix[1] and matrix[2] as they are just copies of matrix[0]. A rule of thumb is that you should have the same number of calls to delete as you have calls to new.
You need to read this: http://isocpp.org/wiki/faq/freestore-mgmt#multidim-arrays
In a nutshell, allocate your matrix in a single chunk if it is rectangular:
int* matrix = new int[3*3];
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
matrix[i*3+j] = x;
delete [] matrix;
Since it's allocated in one chunk you can also delete in one chunk.
Or you can do something similar to what you're doing, but do an allocation for each row. Be sure to delete each row first, then the matrix.
The linked article also has info about wrapping up the nasty pointer/array stuff in a class.
The array of pointers may be unnecessary. You could just allocate the 1D array of 9 elements and do the math to convert 2D indexes to 1D indexes.
In addition to swapping around the delete[] operations, you should consider what happens when an allocation fails. If the second allocation throws std::bad_alloc, your program leaks the memory from the first allocation. A correctly-written matrix class (as suggested by Fred Larson) would handle memory deallocation for you.
Every element in the matrix array is an int[], in addition to that, matrix itself is an array of int* (int*[]), taking these rules into account you should do
delete [] matrix[i] { i=0,1,2 }
and then do
delete [] matrix to delete the matrix itself.
Hope this helps.
Thanks
Related
I am using Dr. Memory to debug my code. It gives me the following message:
INVALID HEAP ARGUMENT: allocated with operator new[], freed with operator delete
However, whenever I use delete[] instead of delete, it gives me the same error. The error occurs in the following lines:
for (int x = 0; x < width; ++x)
{
delete data[x];
}
delete [] data;
Variable data is being allocated as follows:
data = new char*[width];
for (int i = 0; i < width; ++i)
{
data[i] = new char[1];
}
Could someone please help me out?
You currently allocate the elements with
data[i] = new char[1];
and delete them with
delete data[x];
As you allocated them with the new[] you need to delete them with delete [].
delete [] data[x];
You need to match the second new[] (data[i] = new char[1]) too:
for (int x=0; x<width; ++x){
delete [] data[x];
}
delete [] data;
Since you are using c++, and not C...
Re-factor the code to use the STL and std::string to create vectors of std::strings in the program.
Use of std::string will likely eliminate the memory leak.
Okay, I'm writing a program that will perform different functions on an array. If necessary, the array will need to change capacity. The instructions are:
Create an new array.
Copy the contents from the old array to the new.
Delete the old array.
This part is understand, but what I don´t understand is how to keep a reference to the array that the functions will work with. This is my code for creating a new array and move over the elements.
int newSize = m_size*2;
double *tempArray= new double[newSize];
for(int i=0; i<m_size-1; i++)
{
tempArray[i] = arr[i];
}
delete []arr;
for(int i=0; i<m_size-1; i++)
{
arr[i] = tempArray[i];
}
delete []tempArray;
}
All the other methods use arr so I would like to reference back to that. A pointer won´t work since it only points to the first element. How can I use my arr variable to refer to an array?
In C and C++ dynamic arrays are usually represented by a pointer to the first element and the number of elements. So I'm assuming the following declarations:
double *arr;
int m_size;
If by any chance you have arr decleared as a real array double arr[..], then you cannot do delete []arr nor change its size!
Then your code should be along the lines of:
int newSize = 2*m_size;
double *tempArray= new double[newSize];
for(int i=0; i<m_size-1; i++)
{
tempArray[i] = arr[i];
}
delete []arr;
arr = tempArray;
m_size = newSize;
But now I wonder: why m_size-1 in the loop?
And also, you can just do:
memcpy(tempArray, arr, sizeof(*arr) * m_size)); //or m_size-1?
All this is nice if it is an exercise. For real code it almost always better to use std::vector<double> and the resize() member function.
You got undefined behaviour in your code.
delete []arr;
for(int i=0; i<m_size-1; i++)
{
arr[i] = tempArray[i];
}
You delete the memory arr was pointing to and then assign to the deleted memory inside the loop. Instead you should just write:
delete []arr;
arr = tempArray;
The whole code would be:
int newSize = m_size*2;
double *tempArray= new double[newSize];
for(int i=0; i<m_size-1; i++) // -1 might be wrong, look below for a comment on this line.
{
tempArray[i] = arr[i];
}
delete []arr;
arr = tempArray;
m_size = newSize // stolen from the others *cough* since I oversaw the need.
// note that I don't call delete on tempArray.
}
Also I don't know how you allocated your first array but if you made it calling new double[m_size] then you'd want to delete the -1 in the loop condition of the for loop since you're checking for i < m_size and not i <= m_size.
You need to allocate memory for ar after deallocating it.
int newSize = m_size*2;
double *tempArray= new double[newSize];
for(int i=0; i<m_size-1; i++)
{
tempArray[i] = arr[i];
}
delete []arr;
ar = new double[newSize];
for(int i=0; i<m_size-1; i++)
{
arr[i] = tempArray[i];
}
delete []tempArray;
delete []arr;
for(int i=0; i<m_size-1; i++)
{
arr[i] = tempArray[i];
}
Oops. Don't access after delete. And don't delete unless it was allocated with new.
You simply can't reallocate an array declared as
int arr[100]
or similar.
Based on the code you've given, what you're currently performing is:
Create a new array (tempArray)
Copy the contents of the old (arr) array to the new (temp) - (note - what happens if you make the new array smaller than the old?)
Delete the old array
Copy the new values back into the deleted remains of the old array (note - you deleted arr so you can't use it now!)
Delete the new array (so everything is gone)
Basically, you need to fix step 2, to handle sizes, and get rid of steps 4 and 5 entirely - you just need to re-assign arr instead:
arr = tempArray
You just have to declare the array arr and put the values in it. You can refer to the array through its pointer arr or each element with arr[element_id].
You have a couple of options here:
Take the C-style approach of just storing the pointer to the first element like you have, plus the length. From those two you can calculate anything you need.
Use std::vector. It holds an array, allows you to easily resize it with functions like emplace_back, and can tell you its length with the size function.
The second approach is certainly preferred. If you're in C++, you should usually be using std::vector instead of raw arrays, unless you're looking for a fixed-sized one. In that case use std::array.
You also get the added benefit of copying a vector being as simple as vector1 = vector2;.
I've searched through many topics here, but they didn't seem to answer me exactly.
I'm trying to do some dynamic reallocation od arrays in C++. I can't use anything from STL libraries as I need to use this in homework where STL (vectors,...) is explicitly forbidden.
So far, I've tried to elaborate with code like this:
int * items = new int[3]; //my original array I'm about to resize
int * temp = new int[10];
for (int i = 0; i < 3; i++) temp[i] = items[i];
delete [] items; //is this necessary to delete?
items = new int [10];
for (int i = 0; i < 10; i++) items[i] = temp[i];
delete [] temp;
This seem to work, but what bothers me is the excessive number of iterations. Can't this be done anyhow smarter? Obviously, I'm working with much larger arrays than this. Unfortunately, I have to work with arrays though.
edit: When I try to do items = temp; instead of
for (int i = 0; i < 10; i++) items[i] = temp[i]; and try to std::cout all my elements, I end up with losing first two elements, but valgrind prints them correctly.
Yes, the first delete[] is necessary. Without it, you'd be leaking memory.
As to the code that comes after that first delete[], all of it can be replaced with:
items = temp;
This would make items point to the ten-element array you've just populated:
int * items = new int[3]; //my original array I'm about to resize
int * temp = new int[10];
for (int i = 0; i < 3; i++) temp[i] = items[i];
delete [] items; //delete the original array before overwriting the pointer
items = temp;
Finally, don't forget to delete[] items; when you are done with the array.
The containers of the STL were made to ease work like this. It is tedious, but there is not much of a choice, when you need to use C-arrays.
The deletion of
delete [] items;
is necessary, as when you abandon the reference to the array, which you would do with assigning a new reference in
items = new int [10];
will cause a memory leak, so this is necessary.
I have a triple pointer to an Object in C++ and I need to free the entire thing after use.
MyClass *** foobar = new MyClass **[10000];
How do I write the delete statement for this.
It depends on how you allocate the pointers-to-pointers. If you do:
int x;
int* p = &x;
int** pp = &p;
int*** ppp = &pp;
Then you don't have to delete anything.
On the other hand, if you do:
int* p = new int;
int** pp = &p;
int*** ppp = &pp;
Then you only have to delete p. For:
// i.e., allocate 1000 ints, return a pointer, and then get the address of that pointer
int** pp = &(new int[1000]);
// Oh, and get the address of the int**
int*** ppp = &pp;
You have to delete[] *pp (i.e., dereference pp to get the original pointer to the array of ints, and then delete[] the array).
How do you alloc it? Generally, if A is pointer to B, B is pointer to C and C is pointer to D (data), you need to free D, then C and B as the last one.
Anything you new[], you will have to delete[]. It's that simple.
If you do it at several levels, you will have to delete[] in the reverse order of the new[]'s.
If the only allocation that you have done is the one you show in the question, then you only need to do:
delete [] **foobar;
As that is the only memory that was actually acquired. If you have allocated memory to elements inside foobar, then you must clear them up in reverse order of creation.
Note that in most cases these types of structures can be simplified. For example, if the actual data to hold is a cube, you can allocate a single block of 1000*1000*1000 elements (that is a HUGE amount of them) and deallocate it with a single delete []. If you wrap the memory inside a class, then you can provide operator() that will map from three indices to the unique element in the sequential container. Take a look at the C++FAQ lite here.
3D memory allocation
int ***allocate3D(int ***mat, int k, int l, int m) {
mat = (int***) malloc( sizeof(int)*k*l*m );
for(int i=0;i<k;i++)
mat[i] = (int**) malloc ( sizeof(int)*l*m );
for(int i=0; i<k; i++) for(int j=0; j<l; j++)
mat[i][j] = (int*) malloc ( sizeof(int)*m );
return mat;
}
3D matrix deallocation:
void deAllocate3D(int ***mat, int k, int l, int m){
//Delete in reverse order of allocation
for(int i=0; i<k; i++) for(int j=0; j<l; j++) { free(mat[i][j]); mat[i][j] = NULL; }
for(int i=0; i<k; i++) { free(mat[i]); mat[i] = NULL; }
free(mat); mat = NULL;
}
Find the full source code here
I have this in my code:
double** desc = new double* [size_out];
for (int i = 0; i < size_out; i++)
desc[i] = new double [size_in];
How do I delete this desc?
Should I do:
delete [] desc;
or
for (int i=0; i<size_out; i++)
delete [] desc[i];
delete [] desc;
or
for (int i=0; i<size_out; i++)
delete [] desc[i];
delete desc;
?
Simple rules to follow:
for each allocation, there has to be a deallocation (ex1 is therefore wrong)
what was allocated using new should be freed using delete, using new[] should be deallocated using delete[] and using malloc should be deallocated using free (ex3 is therefore wrong)
Conclusion, ex2 is OK.
Your code shouldn't compile. The type of an array new expression is a pointer to the type of array element being created (the value is a pointer to the first element of the allocated array).
So the type of new double**[size_out] is double ***.
Whenever you use the array form of new, you must use the array form of delete even if you only allocate an array of size one.
double*** desc = new double**[size_out];
for (int i=0; i<size_out; i++)
desc[i] = new double*[size_in];
for (int i=0; i<size_out; i++)
delete[] desc[i];
delete[] desc;
Note that you still haven't allocated any double, just pointers.
Did you really want this instead?
double** desc = new double*[size_out];
for (int i=0; i<size_out; i++)
desc[i] = new double[size_in];
for (int i=0; i<size_out; i++)
delete[] desc[i];
delete[] desc;
Your deletion should mirror your allocation.
Since you used new [] to allocate the outer array, and new [] (in a loop) to allocate the inner arrays, do likewise for deletion. That is: your second solution is correct; delete [] the inner arrays in a loop, and finally the outer array via delete [] also.
That said, a (much, much) better solution in C++ would be to use a nested std::vector:
// Declaration and initialization:
vector<vector<double> > desc(size_out, vector<double>(size_in));
// No deletion!
Solution 2 is the right one : each cell points to a dynamically allocated array that should be deleted using delete[]. Finally,
the desc array itself should be deleted using delete[].
Bonus solution 4 : avoid using arrays and switch to std::vector<std::vector<double> >.
I would do
for (int i=0; i<size_out; i++)
delete [] desc[i];
delete [] desc;
for each array allocated with new [], you have a corresponding delete [].
And as Rupdolph says: stop using C-arrays, and start using std::vector. You will have less bugs (hundred times less bugs).