Error when deleting allocated memory in C++ - c++

I am new to C++ and am trying to understand the proper way to deallocated array memory. I am getting the following error when try to delete an allocated pointer array:
"pointer being freed was not allocated."
My pointer is defined as:
T * al ;
al = new T[top] ;
While my destructor for the class where the pointer al is defined in is:
for( int i = 0 ; i < current ; i++ )
delete( al+i ) ;
delete [] al ;
The destructor for the class T is:
for( int i = 0 ; i < length ; i++ )
delete( p+1 ) ;
delete [] p ;
Where p is defined as:
char *p ;
length = strlen( str ) ;
p = new char[length] ;
strcpy( p, str ) ;
How to properly allocate memory and/ or how to fix this?

Just use the delete [], not the loop in addition. delete [] will delete each element of the array.
Also, your loop in the class T destructor is trying to delete p+1 instead of p+i

To be specific, you should delete like so:
int *a = new int; // One allocated
delete a; // So delete one
int *b = new int[50]; // 50 allocated
delete[] b; // Just use delete[], don't delete every one
int **c = new int*[50]; // 50 pointers to ints
for (int i = 0; i < 50; i++)
c[i] = new int; // each c[i] points to a pointer to a new int
for (int i = 0; i < 50; i++)
delete c[i];
delete[] c;
Use delete when you use new, delete[] when you use new[].
It's actually wrong to do the following:
int *a = new int[50];
// do stuff...
for (int i = 0; i < 50; i++)
delete &a[i]; // equivalent to delete (a + i);
delete[] a;
You only do a delete[] a, never the delete (a + i).

Related

why am I consistently getting malloc errors when I try to delete my 2D array made using pointers?

I'm trying to delete my 2D array, but I consistently get errors when I try to delete it, we have to work backwards so I delete the elements first, then the column array, then the row array. here is my code for the constructor in my class, MyMatrix:
private:
int m; //rows
int **ptr; //ptr to first dimension
int n; // columns
public:
MyMatrix() //constructor
{
m = 0;
n = 0;
ptr = new int*[m];
int *length_arr = new int[m];
for (int i = 0; i <= m-1; i++)
{
*(ptr+i) = new int[n];
*(length_arr+i) = n;
}
}
and my destructor looks like this:
for(int i = 0; i <= m-1; i++)
{
for (int j = 0; j <= n-1; j++)
{
delete ((*(ptr+i))+j);
}
delete[] *(ptr+i);
}
delete[] ptr;
the error I'm getting is:
assg7(2677,0x100de3d40) malloc: *** error for object 0x12d606804: pointer being freed was not allocated
I've wracked my brain for where I can fix this, for context, I'm doing an assignment with operator overloading. I specifically need a delete function to work properly for my = assignment overloading since I want to delete and again reallocate memory to equate two matrices, but the terminal is showing malloc errors and is thus not equating the matrices.
for additional info here is my = overloading code:
void operator = (const MyMatrix &obj)
{
if(n == obj.n && m == obj.m)
{
//for loop to equate elements in this-> to the elements of the passed object
}
else
{
for(int i = 0; i <= m-1; i++)
{
for (int j = 0; j <= n-1; j++)
{
delete ((*(ptr+i))+j);
}
delete[] *(ptr+i);
}
delete[] ptr;
// the code for assigning new memory according to the passed objects rows and colums goes here
//then for loop to equate elements in this-> to the elements of the passed object
}
}
thanks.
You have two "levels" of new, so three "levels" of delete can't be right.
Spell out your deletion loop, using indexing instead of pointer arithmetic:
First iteration:
delete ptr[0]+0;
delete ptr[0]+1;
...
delete ptr[0]+n-1;
delete [] ptr[0];
Second iteration:
delete ptr[1]+0;
delete ptr[1]+1;
...
delete ptr[1]+n-1;
delete [] ptr[1];
You're passing to delete a pointer to the first element of ptr[0], a pointer to the second element of ptr[0], a pointer to the third element of ptr[0], ...
But the things you allocated were ptr[0], ptr[1], ... ptr[m-1], not their individual elements.
Remove the innermost deletion loop.
(And don't mess around with pointer arithmetic when you can use indexing.)
I don't know how you would want to allocate memory space by m length if it is set to 0 by default.
To me it looks like you set m = 0 and then try to allocate by 0 length or how do you control the length of your dimensions?
Maybe edit your constructor to:
MyMatrix(int m, int n)
{
this->m = m;
this->n = n;
...

how to delete a char**

I am basically wondering how to delete a double pointer, for example char**. This is because I ran into an access violation problem which I don't quite understand. Here is the code:
StatsManager::_statsNameList = new char*[StatsManager::MAX_STATS_COUNT*StatsManager::MAX_CHANNEL_COUNT*StatsManager::MAX_ROI_COUNT];
if(NULL != StatsManager::_statsNameList )
{
for (int i = 0; i < StatsManager::MAX_CHANNEL_COUNT; i++ )
{
for (int j = 0; j < StatsManager::MAX_ROI_COUNT; j++ )
{
for (int k = 0; k < StatsManager::MAX_STATS_COUNT; k++ )
{
char* pList = StatsManager::_statsNameList[i*area + j*StatsManager::MAX_STATS_COUNT + k];
if (NULL != pList)
{
// following line is where the exception throws
delete[] StatsManager::_statsNameList[i*area + j*StatsManager::MAX_STATS_COUNT + k];
StatsManager::_statsNameList[i*area + j*StatsManager::MAX_STATS_COUNT + k] = NULL;
}
}
}
}
}
delete[] StatsManager::_statsNameList;
StatsManager::_statsNameList = NULL;
I am very confused because for the inner loop where the exception throws, I watched the pLsit is a bad pointer, so how come the if (NULL != pList) still get passed?
And what is the correct way to delete a char**? Thanks a lot.
Usually you have to follow two points:
If you used new[] for allocation use delete[] for deallocation, and if new was used for allocation delete has to be used to free the memory;
You have to free the memory on every level it was allocated, e.g.
int **pp = new *int;
*pp = new int;
**pp = 5;
delete *pp;
delete pp;
So, delete of the same type as new has to called the same number of times, but in reverse order.
You need to use the delete or delete[] operator that matches the operator used to allocate. So new[] is followed by delete[], and new by delete.
You cannot delete a char**, it's just a pointer to a pointer to a char. It depends on the object it's actually holding. Logically, a char** would itself contain an array like new char*[x], and is itself filled with objects allocated with new char[x]. In that case you need to loop over the array and delete[] those, then delete[] the outer array.

declare and delete this version of a 2D array in c++

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.

How to resize a dynamically allocated array of polymorphic objects?

I have a dynamically allocated array of polymorphic objects that I would like to resize without using STL library (vectors, etc). I've tried moving the original to a temporary array, then deleting the original, then setting the original equal to the temporary, like this:
int x = 100;
int y = 150;
Animal **orig = new Animal*[x];
Animal **temp = new Animal*[y];
//allocate orig array
for(int n = 0; n < x; n++)
{
orig[n] = new Cat();
}
//save to temp
for(int n = 0; n < x; n++)
{
temp[n] = orig[n];
}
//delete orig array
for(int n = 0; n < x; n++)
{
delete orig[n];
}
delete[] orig;
//store temp into orig
orig = temp;
However, when I try to access the element for example:
cout << orig[0]->getName();
I get a bad memeory alloc error:
Unhandled exception at at 0x768F4B32 in file.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x0033E598.
//delete orig array
for(int n = 0; n < x; n++)
{
delete orig[n];
}
For this particular case, don't do this. You are actually deleting the objects not the array. So all the objects in the temp array are pointing to invalid locations. Simply do delete [] orig to deallocate the original array.
You are copying wrong. Instead of copying your temp array is simply pointing to the same location as that of the orig. Now when you delete the orig the temp pointers point to an invalid location.
//save to temp
for(int n = 0; n < x; n++)
{
//temp[n] = orig[n];
// Try this instead
strcpy(temp[n], orig[n]);
}

Deleting a Triple Pointer in c++

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