My question arises from this answer.
In the comments he mentions that I should delete the allocated dynamic 2D array in the reverse order.
However I did not understand much why this should be done. Here is the code:
//intialising array
int size = 10000;
double **array = new double[size];
for(int i = 0; i < size; i++)
array[i] = new double[size];
//conventional de-initialise
for(int i = 0; i < size; i++)
delete[] array[i];
delete[] array;
//reverse de-initialise
for(int i = size - 1; size >= 0; i--)//notice reverse order here
delete[] array[i];
delete[] array;
So my question is, is there any significant difference between the 2 methods of de-allocating a 2D array?
In your example there's no difference - you create 100K pointers, and then allocate memory for each. It doesn't matter how you allocate/deallocate memory and assign it to pointers array.
However your question is about why reverse deallocation was in another post, and opposite to your example it matters - counter variable is reused to countdown from last allocated object down to 0, when new memory allocation failed. If deallocating other direction you'd need additional variable there:
try
{
array = new double*[size];
// Don't shadow counter here.
for(counter = 0; counter < size; counter++)
{
array[counter] = new double[size];
}
}
catch(std::bad_alloc)
{
// delete in reverse order to mimic other containers.
for(--counter; counter >= 0;--counter)
{
delete[] array[counter];
}
delete[] array;
Related
I try to clean the memory to delete pointers. But the last instruction (delete array[i]) generate this error :
pointeurs-tableau(14994,0x110a67600) malloc: *** error for object 0x7ff7bb760760: pointer being freed was not allocated
But I don't know why.
#include <iostream>
#include <random>
#include <ctime>
using namespace std;
int main()
{
default_random_engine gen(time(0));
uniform_int_distribution<> dis(1, 100);
const int max = 20;
int* array[max];
// un tableau normal
int val[max];
for (int i = 0; i < max; i++) {
val[i] = dis(gen);
}
for (int i = 0; i < max; i++)
{
array[i] = &val[i];
}
//... modifying function on the array
// show the array
for (int i = 0; i < max; i++) {
cout << val[i] << " ";
}
// deleting pointeurs (problematic !!!!)
for (int i = 0; i < max; i++)
{ delete array[i];}
delete[] array;
return 0;
}
Could you help me, please?
delete operator must be used only on a dynamically allocated memory (with the new).
In your case you have an array int val[max]; with automatic storage duration. And array of pointers int* array[max]; also with automatic storage duration.
Automatic storage duration means memory for arrays int val[max]; and int* array[max]; will be allocated when execution enter in the scope they declared and will be freed when execution lives the scope (at your case main function).
But when you trying to call delete array[i]; you force compiler to attempt clear element from int val[max] onto which array[i] pointing to. But it can't do that because this value never have been allocated on the heap with new.
// Edit
As you mentioned in comment to this answer you added changes to your code:
int **array = new int*[max];
for (int i=0; i < max; i++) {
array[i] = new int;
}
An still have the same error;
The reason behind it most likely is that you still have this cycle
for (int i = 0; i < max; i++) {
array[i] = &val[i];
}
int** array; item: array[i] - is a pointer.
You allocated memory on the heap and stored address of this memory into that pointer:
array[i] = new int;
Lets say new int; returned address ADDRESS_FROM_HEAP
Then you took address of int val[max]; by &val[i] and assigned it to the pointer array[i] = &val[i];
Lets say &val[i] equal to ADDRESS_FROM_STACK
Then you trying to delete array[i];
But at this moment array[i] == ADDRESS_FROM_STACK;
Not only delete unable to free memory on ADDRESS_FROM_STACK, you also lost ADDRESS_FROM_HEAP and memory by this address will not be freed.
If you would change your loop to this
for (int i = 0; i < max; i++) {
*array[i] = val[i];
}
You will store a COPY of val[i] in the memory pointed by array[i] pointer.
But by looking at your code I can't honestly see why you allocate any memory dynamicly.
If you will just leave code as it is in your original question and just remove all delete statements, it will work just fine.
In my code, I have a 2D array of pointers to my data:
Data***
The reason I'm not using array notation is because the size is not determined at compile time.
So, somewhere in my code I allocate all the necessary space:
arr = new Data **[xVals];
for (int i = 0; i < xVals; i++)
{
arr[i] = new Data *[yVals];
for (int j = 0; j < yVals; j++)
{
arr[i][j] = nullptr;
}
}
And then fill the array with my proper pointers some time later on.
Furthermore, the pointer also gets stored in a std::vector:
for(...) {
for(...) {
// Conditional statement; not the whole array gets filled, some parts stay nullptr
...
arr[xCoord][yCoord] = new Data(...);
myVector.push_back(arr[xCoord][yCoord]);
}
}
... // Do some other stuff that takes advantage of the spatial properties of the 2D array
Once I'm done using the 2D array, I want to delete it, but NOT delete the Data-pointers themselves, since they are now stored in my vector.
I've been trying the following:
for (int i = 0; i < xVals; i++)
{
// Delete all "column" arrays
delete[] arr[i];
}
// Delete
delete[] arr;
However, I get a corrupted heap error CRT detected that the application wrote to memory after end of heap buffer, so I'm not sure what exactly I did wrong there. How do I delete a 2D array without deleting the data it held?
int *array[10];
for(int i = 0; i < 10; i++)
array[i] = new int[10];
//...
void passFunc(int *a[10]) //array containing pointers
{
//...
}
passFunc(array);
Im trying to figure out how to declare and delete this version of a 2D array. I started using int ** array, but in order to make one section of code easier, I need to switch to *[]. Can anyone help me out?
I have tried compiling my actual code (the above code is just an example), which looks like this:
int* filedata[LENGTH] = new int*[LENGTH]; //ERROR: array must be initialized with brace- enclosed identifiers.
EDIT:
Thanks!
Something like that
int** array = new int*[sizeX];
for(int i = 0; i < sizeX; ++i)
array[i] = new int[sizeY];
To delete
for(int i = 0; i < sizeX; ++i)
delete [] array[i];
delete [] array;
If I have understood correctly what you want then the allocation and deallocation will look as
int ** filedata = new int * [LENGTH];
for ( int i = 0; i < LENGTH; i++ ) filedata[i] = new int [LENGTH];
//...
for ( int i = 0; i < LENGTH; i++ ) delete [] filedata[i];
delete [] filedata;
Alternate version to the ones given:
int** array = new int*[sizeX];
int *pool = new int[sizeX * sizeY];
for(int i = 0; i < sizeX; ++i, pool += sizeY)
array[i] = pool;
To delete:
delete [] array[0];
delete [] array;
The advantage of using this is:
Only two calls to new[] and delete[] are required, regardless of the number of columns. In the previous answer, the number of calls to new and delete depend on the number of columns. This reduces fragmentation, and also will probably give you a speed increase if the number of columns is very large.
The data is contiguous. You can access any element in the 2d array from any other element using a simple offset.
The disadvantage is that the number of columns for each row needs to be the same, otherwise it becomes very difficult to maintain.
I have a 2D array with size 4 (4 rows). To make the array size 2 (2 rows), can I use following? (for our hw assignment details are not specified and the code should be suitable with common c++ standarts)
I am removing second half of the array.
const int newSize = flightsArraySize/2;
for(int i = newSize-1; i < flightsArraySize-1; i++)
delete [] flights[i];
Or do I have to recreate flights array with size 2?
Supposing that you have created a 2D array using new like this:
int **arr = new int*[rows];
for(int i=0; i<rows; ++i)
arr[i] = new int[cols];
Then to resize it you'd have to do something like:
int newRows = rows/2;
// Create a new array for the right number of rows.
int **newArr = new int*[newRows];
// Copy the rows we're keeping across.
for(int i=0; i<newRows; ++i)
newArr[i] = arr[i];
// Delete the rows we no longer need.
for(int i=newRows; i<rows; ++i)
delete[] arr[i];
// Delete the old array.
delete[] arr;
// Replace the old array and row count with the new ones.
arr = newArr;
rows = newRows;
But seriously, this is all so much easier if you just use vector:
std::vector<std::vector<int>> v(rows);
for(int i=0; i<rows; ++i)
v[i].resize(cols);
v.resize(v.size()/2);
Well, it deallocates the memory on which pointed the second half of pointers. But the poiters themselves will stay, the array of pointers will not be shortened.
EDIT
Oh, sorry. It seems as a mistake. If you have code like this:
int **ptr = new int*[4];
for(int i = 0; i < 4; i++)
{
ptr[i] = new int[4];
}
Then when you type
delete[] ptr[3];
It will delete the whole array, so you can create new like this:
ptr[3] = new int[any_number];
Is this what you mean? Sorry, I read too fast...
How can I dynamically allocate a two dimensional array where each row contains variable element? How can I free this memory?
Actually you probably want a vector of vectors, something like this:
std::vector<std::vector<int> > vector_2d;
This way you'll benefit from the automatic memory management of the vector rather than having to manually manage the memory of an array of pointers to arrays of data.
You would need need to use pointers:
int ** a;
a = new (int*)[5];
for(int i = 0; i<5; i++)
{
a[i] = new int[x]; //where x is the size of this row
}
Something like this should work, but I didn't test it.
Just for the sake of completeness:
int ** a;
a = new (int*)[5];
for(int i = 0; i<5; i++)
{
a[i] = new int[x]; //where x is the size of this row
}
for(int i = 0; i<5; i++)
{
delete[] a[i];
}
detete[] a;