heap corruption when deleting array pointer C++ - c++

So, I'm getting a heap corruption error in the Expand method for an Ordered List Class I'm working on. The expand method is called when the client tries to Insert() a new item into the list, and there isn't currently room left in the array. When I take the delete line out, the program runs fine, but I know I have an inaccessible object each time it expands. However, when I put the delete line in, the program explodes at run-time.
Additionally, this only happens in my Expand() method. It doesn't do this in my Contract() method, which is called each time there is a deletion from the list that brings the number of list elements down below 1/4 the total space currently available, it cuts the size in half. I can delete the old list in this method without any problems.
GetListPtr(), SetListPtr(), and GetLength() are all inherited from a ListClass object, which I received in the form of a header file and object code, so I'm not sure exactly how they work. ItemType is a struct, only containing an integer field, key.
I've read a number of questions on here already and didn't find any that seemed to provide any help in regards to my situation.
void OrdListClass::Expand()
{
ItemType* newList = new ItemType[size * 2];
ItemType* temp = GetListPtr();
size = size * 2;
// Copy the current list to the new list.
for(int i = 0; i < GetLength(); i++)
newList[i] = temp[i];
// Point to the new list.
SetListPtr(newList);
// Delete the old list
delete temp; <-- This line
// Reset the pointers
temp = nullptr;
newList = nullptr;
}
void OrdListClass::Contract()
{
ItemType* newList = new ItemType[size / 2];
ItemType* temp = GetListPtr();
size = size / 2;
// Copy the old list into the new one
for(int i = 0; i < GetLength(); i++)
newList[i] = temp[i];
// Set the list pointer to point to the new list
SetListPtr(newList);
// Delete the old list
delete temp;
temp = nullptr;
newList = nullptr;
}
Thanks again for reading this, any and all help is appreciated.

I assume that your list was allocated with:
ItemType* newList = new ItemType[size * 2];
If that's the case, you need to do:
delete[] temp;
Elements allocated with new[], need to be deleted with delete[].
http://www.cplusplus.com/reference/new/operator%20delete[]/

Related

C++ Delete Pointer to array of pointers without deleting the contents [Memory Leak]

I'm writing my own array sorting method and I have created a duplicate array to stored the objects as they are stored. The arrays are both arrays of pointers and so I need to delete my temporary array without deleting the items it points to. In the code snippet below I am leaking memory as I either delete all the items or do not delete anything.
//In constructor initialiser list
m_listArray( new PathFindingTile*[maxSize] )
void sort()
{
auto** sorted = new PathFindingTile*[m_size];
sorted[0] = m_listArray[0];
for (int i = 1; i < m_size; i++)
{
sorted[i] = m_listArray[i];
for (int j = i; j - 1 >= 0; j--)
{
if (*m_listArray[j] < *m_listArray[j - 1])
{
PathFindingTile* temp = sorted[j - 1];
sorted[j - 1] = m_listArray[i];
sorted[j] = temp;
}
else
{
sorted[i] = m_listArray[i];
break;
}
}
}
m_listArray = sorted;
//Both 'delete sorted' and 'delete[] sorted' delete the contents of sorted, but I'd only like to delete the array pointer
delete sorted;
}
How can I transfer the duplicated list back to the original list without leaking memory?
m_listArray = sorted;
On this line, you leak the array that m_listArray was pointing at before the assignment.
You must delete the array before (the only) pointer to it is overwritten. Also, delete is wrong for deleting pointers from new[]. delete[] is correct:
delete[] m_listArray;
m_listArray = sorted;
P.S. It is not a good idea to have bare pointers to owned memory. I recommend using std::vector instead. Also, it should not be necessary to allocate a new array in order to sort one. You could simply swap elements within the array.
I think you just remove pointer to the first element in the array. I believe you need to release the array with the follow command.
delete[] sorted
Read more about delete and delete[] [delete vs delete[]]1

Deleting an element from an array of objects

I tried to write a function that gets an object ("Stone") and deletes the stone from a given array. code:
void Pile::del_stone(Stone &s)
{
Stone *temp = new Stone[size - 1];//allocate new array
for (int i = 0;i <size;++i)
{
if (s != Pile_arr[i])//if the given object to delete is different from the current
{
temp[i] = Pile_arr[i];//copy to the new array
}
else
{
i--;
}
}
Pile_arr = temp;
set_size(this->size - 1);
temp = NULL;
delete[] temp;
}
Pile_arr is a member of Pile class.
The problem is that i get an infinite loop, because i decrease i. I cant figure out how to solve this issue. Any ideas?
Use two indexes: i and j. Use i to know which element of the original array you are looking and j to know where to put the element in temp.
You need to use a separate counter to track where new elements should be placed.
I have used n below:
Stone *temp = new Stone[size - 1];
int n = 0; // Stores the current size of temp array
for (int i = 0;i <size;++i) {
if (s != Pile_arr[i]) {
temp[n++] = Pile_arr[i];
}
}
It's also worth considering the case where s is not found in the array, as this would cause a runtime error (Attempting to add size elements to an array of size size - 1).
Using a STL container would be a far better option here.
This function will:
Allocate a new array of length size-1
Search for the intended object
If you find it, copy it to the same exact position in the array
If you don't --i
Finally, ++i
First of all, this function is bad for 3 reasons:
It only copies one item over--the given item. You have an array with only 1 object.
It copies the item from index to index. Since the final array is one smaller, if the object is at the max original index, it will be out of bounds for the new array.
If the object is not immediately found, the array will get stuck, as you decrease the index, and then increase it using the loop--you'll never move again.
Stone *temp = new Stone[size - 1];//allocate new array
for (int i = 0;i
Instead:
Cache the found object, then delete it from the original array or mark it. temp = found object
Copy the array, one by one, without copying empty spaces and closing the gap. Copy temp_array[i] and increment i if and only if temp_array[j] is not marked/deleted. Increment j
Decide where to put the found object.
Once again, you can decide to use separate indexes--one for parsing the original array, and one for filling the new array.

C++ resize array of pointer without STL (vector...)

I got following problem.
I want to resize my array of pointers on structure ( car ) . I got following code.
Class Car{
...
char * Owner_Name;
char * carID
};
Class Register {
...
int CarCNT;
int car_num_default;
Car ** dataBase;
Register ()
{ //constructor
car_num_default = 5 ; //for example;
dataBase = new Car * [car_num_default];
}
};
Now when I add 6th. car I need to resize my array of pointer to car. How should I do that without create any memory leak ? Or memory error ? :)
I tried folowing code but it makes some memory leaks..
void Register:: Add ( const char * carID, const char * owner)
{
if (carCNT == car_num_default) // now it's full array need resize
{
car ** tmp = new car * [carCNT]; //create new array ;
for(int i = 0 ; i < carCNT;i++)
tmp[i] = new car(databaze[i]->car_ID,databaze[i]->owner_name);
free(database); //free memory and than alloc new bigger
database = new car * [car_num_default * 5];
for(int i = 0; i < carCNT; i++)
data_by_RZ[i] = tmp [i];
free(tmp);
car_num_def = car_num_def * 5;
}
databaze[carCNT] = new car(....);
carCNT++;
}
Thanks for any help!
Here's a list of obvious bugs in your memory management:
You allocate with new[] but deallocate with free. See Is there any danger in calling free() or delete instead of delete[]?
On reallocation, you create new car instances and copy the data of existing car objects instead of copying the pointers to the existing car obejcts. This causes all the previous cars objects to leak. This bug is only when copying database to the tmp table. The copy from tmp to the new database would be correct if tmp contained the pointers to the old car objects.
You needlessly create a tmp array and copy the database to it. You should simply create the new, bigger array, copy, deallocate the old and then set the database pointer. This bug does not cause a leak, but is entirely pointless and does waste memory bandwidth.*
* Here's the code as requested:
Car** tmp = new Car*[car_num_default * 5];
for(int i = 0; i < CarCNT; i++)
tmp[i] = database[i];
delete[] database;
database = tmp;
Remember that functions destroy their parameters after the function finishes its execution.
Since you are passing carID and owner as pointers and inserting them into the array, the values are destructed after execution and the pointers placed inside the array become invalid causing the leak. Use pointers only when you want to make a change to the pointer itself but never store it as it will soon be destructed.
It seems that you are using pointers in places you shouldnt or where you don't have to. Here is a simpler version of your code that does the same:
Class Car{
...
char Owner_Name;
char carID;
};
Class Register {
...
int CarCNT;
int car_num_default;
Car * dataBase;
Register ()
{ //constructor
car_num_default = 5 ; //for example;
dataBase = new Car [car_num_default];
}
};
void Register:: Add ( const char carID, const char owner)
{
if (CarCNT == car_num_default) // now it's full array need resize
{
car * tmp = new car [carCNT]; //create new array ;
for(int i = 0 ; i < carCNT;i++)
tmp[i] = new car(dataBase[i].car_ID,dataBase[i].owner_name);
free(dataBase); //free memory and than alloc new bigger
dataBase = new car [car_num_default * 5];
for(int i = 0; i < carCNT; i++)
data_by_RZ[i] = tmp [i];
free(tmp);
car_num_def = car_num_def * 5;
}
Car x(...);
dataBase[CarCNT] = x;
carCNT++;
}
Finally, I have four points to make:
1) This doesnt seem like C++ or you are not using proper naming
2) I am not sure how this code complied since most variable names are incorrect (i tried to fix what i came across).
3) Excessive use of pointers (memory locations in other words) is the main cause of memory leaks. Handle them with care and only use them when you have to.
4) IFFF you have to use pointers that much then add destructors (Anti-constructor) like this ~Car or ~Register on any class that is used as a pointer to signal when the element is destroyed. That way you know where the leak is taking place by writing to the console or handle the destruction gracefully.
Hope that helped

Pointers and Objects in C++, x86 Compilation Error

I'm creating a binary tree by linking individual nodes all the way up to the root node, which I return from the method.
MaxWinnerTree::MaxWinnerTree(int elements)
{
WinnerTree(elements);
}
`Node MaxWinnerTree::WinnerTree(int elements)
{
int size = 1;
while (size<elements)
size = size * 2; //gets closest power of 2 to create full bottom row
Node* a[size]; //array of pointers to nodes
for (int i = (2*elements-1); i>0; i--)
{
//Create nodes and link them to parent, right, and left values
if (i > elements-1) //leaf
{
//Create new nodes with data -1, store pointer to it in array
*a[i] = newNode(i,-1,NULL,NULL,NULL);
}
else // not leaf
{
//Create node with data = max of children, store pointer
*a[i] = newNode(i,-1,a[i*2],a[i*2 +1], NULL); //create
a[i]->data = max(a[i*2]->data, a[i*2+1]->data); //gets max
a[i]->right->parent = a[i];
a[i]->left->parent = a[i];
if(i=1)
root = a[i];
}
}
return *root; }
However, trying to create an object in my main method isn't working like it should.
MaxWinnerTree* tree = new MaxWinnerTree(elements);
Gives a standard x86 architecture error, where as
MaxWinnerTree tree = new MaxWinnerTree(elements);
Gives
main.cpp:22: error: invalid conversion from ‘MaxWinnerTree*’ to ‘int’
main.cpp:22: error: initializing argument 1 of ‘MaxWinnerTree::MaxWinnerTree(int)’
Why does the compiler think that my method is returning an int? What is to correct way to create an object in this fashion? In reality, I just need a pointer to the root node, where all my other methods will begin.
Thanks for any help in advance.
Changes I would make:
Change newNode (which you haven't shown us) to return a Node *. If newNode isn't actually allocating a new Node, then you need to rethink its design. Or, move the arguments to newNode into a constructor for Node, and change your code to read new Node( ... args ... ).
Instead of saying *a[i] = newNode( ... ) say a[i] = newNode( ... ) (or whatever you replace newNode with as per my first bullet). What you have written asks the C++ compiler to invoke a copy constructor to copy whatever newNode returned into the object pointed to by *a[i], but from the snippet you shared with us, *a[i] doesn't point to anything yet.
You've built a heap, but with explicit pointers. If you really wanted a heap, you don't need the explicit pointers...
This next line can just ruin your whole day. i=1 assigns 1 to i and then returns 1 as its value, which doesn't really do the right thing. In your case, it'll make your loop stop iterating as soon as it gets to the part of the heap-building where the elements have children.
if(i=1)
root = a[i];

[C++]Memory error thrown at destructor that wasn't there before this code. Trying to make a new dynamic array and populate it

I am working on a lab dealing with queues, which I don't think is entirely relevant. My task is to create a "priority queue" and the best way I could think of to do it is as follows
void IntQueue::enqueue(int num,int priorityOfEntry)
{
if (isFull())
cout << "The queue is full.\n";
else
{
// Calculate the new rear position
//insert correct lab code here haha
if (priorityOfEntry == 1)
{
rear = (rear + 1) % queueSize;
queueArray[rear] = num;
queueSize++;
}
else if (priorityOfEntry == 2)
{
queueSize++;
int* newArray = new int[queueSize];
newArray[0] = num;
for(int counter = 0;counter< queueSize; counter++)
{
newArray[counter+1] = queueArray[counter];
}
queueArray = newArray;
delete [] newArray;
}
else cout << "invalid priority" << endl;
// Insert new item
// Update item count
numItems++;
}
}
I only have 2 priority levels, 1 and 2, that I explain in the main program. when they all have equal priority it of course works fine, but when I bump on up in priority it throws an error at my destructor.
I really don't think this is the right way to approach this lab, but It seems to work.. at least if I can actually get this memory error fixed.
I figure the only problem could be in that I change the address of what the destructor thinks it will delete.. but I thought pointers would already kind of account for that.
I understand I need to learn to debug my own programs. I really do. but sometimes I just stare at code and there is nothing but a brick wall there. Guess that's what a nudge in the right direction is for.
queueArray is a dangling pointer after this:
queueArray = newArray; // Both 'queueArray' and 'newArray' point to
// the same memory after this assignment.
delete [] newArray;
as the memory that queueArray is pointing to has been deleted. Any attempt to access or destroy queueArray is accessing memory that has already been destroyed. The correct order is:
delete[] queueArray;
queueArray = newArray;
Additionally, there is a potential out-of-bounds access in the for loop that performs the copying:
for(int counter = 0;counter< queueSize; counter++)
{
// When 'counter == queueSize - 1'
// 'newArray[counter + 1]' is one past the end.
newArray[counter+1] = queueArray[counter];
}
Here:
queueArray = newArray; // queueArray and newArray point to the same place
delete [] newArray; // that place gets delete[]ed
you are making queueArray point to the same place as newArray, but then you are deleting the array that lies in that location. So queueArray is left pointing to memory you have given back to the OS, i.e it is now a dangling pointer.
You need to delete queueArray[] first, then assign newArray to it.
Okay, I got it, I don't know why I thought I needed to add another member of the array when the priority switched, I think i'm just tired.
So that was the extra array member
and i think that was the only other problem