C++ pointer not null but cannot be freed - c++

I'm implementing an open HashTable. My trouble arises in the destructor, where I iterate through all the buckets in an array, for each array I would delete all the nodes in a linked list.
// Deallocate all buckets
for (int i=0; i<maxBuckets; i++) {
Cell * p = m_data[i];
while (p != nullptr) {
Cell * temp = p;
p = p->next;
delete temp;
}
}
delete [] m_data;
But it reports pointer being freed was not allocated on the delete operation. What is going wrong here?

The error is pretty clear. You tried to delete a value that was not returned by new.
What we don't know is if the value is the address of a non-allocated value, just uninitialized (garbage) or if you've corrupted the heap. You haven't provided information to determine that.
But you do know that the value you are trying to free is not correct, and you need to figure out where it came from.

Related

Leaking memory when not freeing internal cells?

My professor wrote the following code:
template <class T>
Set<T>& Set<T>::operator=(const Set<T>& set) {
if (this == &set) return *this;
T* data_temp = new T[set.size];
try {
for (int i = 0; i < size; ++i) {
temp_data[i] = set.data[i];
}
} catch (...) {
delete[] temp_data;
throw;
}
delete[] data;
data = temp_data;
size = maxSize = set.size;
return *this;
}
And he pointed that temp_data[i] = set.data[I]; calls operator=, and I am wondering why this doesn't leak memory?
For example if operator= failed in the 4th loop then we are deleting temp_data, but what about the values of the first 3 cells in temp_data which were allocated inside operator= code? we aren't freeing them.
For example if operator= failed in the 4th loop then we are deleting temp_data, but what about the values of the first 3 cells in temp_data which were allocated inside operator= code? we aren't freeing them.
new[] allocates the entire array and constructs all of the T objects in it, before the loop is reached. delete[] destructs all of the objects in the array, and deallocates the entire array. So, it is the responsibility of T's constructor and destructor to initialize and finalize T's data members properly.
The loop merely updates the content of the data members of the objects in the array. It is the responsibility of T::operator= to copy and free T's data members properly as needed.
There is no leak in this Set::operator= code. However there is a minor mistake - the loop needs to use set.size instead of size.
for (int i = 0; i < set.size; ++i)
The new array is allocated to set.size number of elements, so that is how many elements the loop needs to copy.
Using size for the loop, if the Set being assigned to is smaller than the Set being copied, the new array won't copy all of the elements. And if assigning to a Set that is larger, the loop will go out of bounds of both arrays.
If you are experiencing a leak, it would have to be in either T::operator= or in T::~T(), neither of which you have shown. Assuming Set::Set() and Set::~Set() are initializing and freeing data properly, this is.
Lets remove some complications from this code. Lets assume T == int and instead of storing many ints we only store one:
int_store& int_store::operator=(const int_store& set)
{
int* temp_data = new int; (1) allocate
try
{
*temp_data = *set.data; (2) assign
}
catch (...)
{
delete temp_data; (3) free temp
throw;
}
delete data; (4) free old
data = temp_data;
}
The method has one allocation int* temp_data = new int (1). It the tries to assign the other sets data to that temp value (2). When this fails the temp has to be deleted (3) otherwise we can replace the old data with the new data stored in temp_data and before doing that we have to delete the old data (4).
There is no allocation in the try block. All memory allocated in the function is either deleted (when assignment fails) or it is used to replace the old data, in which case the old data is deleted before.
If data is an array instead of a single int (almost) nothing changes and there is no leak. The elements you worry about are already allocated in the line T* data_temp = new T[set.size]; and then delete[] temp_data; will delete all of them.

C++ trying to delete Binary Tree and move it to Vector

So I'm trying to write a function that places all of the values of a binary tree into a vector, which will later be used to recreate it. But when I try to call this function, I get an error:
Error in `./bst': double free or corruption (fasttop):
This is the function I'm using. The vector itself is a private variable containing nodes. size() returns the size of the tree and is working.
void BST::swapvector()
{
Node *ptr = m_root;
while (size() != 0)
{
if (ptr->m_left != NULL) {
ptr = ptr->m_left;
} else if (ptr->m_right != NULL) {
ptr = ptr->m_right;
} else {
Node *temp = ptr;
myvector.push_back(ptr); //starting from root, we traverse until we reach the bottom and then add ptr to the vector
ptr = m_root;
delete temp; //once we're finished, we delete temp
}
}
}
Does anyone know why this isn't working? Thanks!
It's obvious why this isn't working.
} else {
Node *temp = ptr;
myvector.push_back(ptr); //starting from root, we traverse until we reach the bottom and then add ptr to the vector
ptr = m_root;
delete temp; //once we're finished, we delete temp
}
You're storing a pointer to Node into vector and then deleting that Node with delete temp. After that pointer stored into vector points to garbage or non-existent memory.
"...a function that places all of the values of a binary tree into a vector..."
No, you're not storing binary tree values, you're storing pointers to binary tree values (Node objects).
There are two things you can do:
If the binary tree will not be freed nor changed for the lifetime of myvector then you can just remove the delete temp; line.
If assumption in the first case is not true, then you need to store Node elements into vector, not pointers to them. So, define myvector as vector<Node> myvector; instead of vector<Node *> myvector; and change myvector.push_back(ptr); to myvector.push_back(*ptr);.
You cannot delete temp after you place it a vector. Also, how is your vector defined? There might be problem there.
Also you should use iterators instead of push_back() function. It doesn't work well with pointers.
And, why does everyone insist on using c-style pointers. Use shared or unique pointers. Please?
Type of error usually signifies that a pointer being freed twice.

How to not delete pointer's value without using shared_ptr

I am implementing a Tree, every Node has Node** inside it for the sons:
class Node {
string word;
Node* father;
Node** sons;
int sonsNum;
....
}
for inserting new son I coudnt find a way instead of making new[] array of Node* and deleting the old one (I cant use list, I am restrected...). but when deleting the old Node** using delete[], even I have saved the pointers inside to another tmp array, its values will be gone! (even Node destrucor is empty! why?). so if I use shared_ptr I think it will solve it, is there a way to do that without shared_ptr?
void insertSon(Node* sn) {
sn->father=this;
Node** tmpSons = sons; //should be shared_ptr? but I dont want that
if(sons)
//delete[](sons); // after this line, tmpSons has garbage!
sons = new Node*[sonsNum+1];
for(int i=0 ; i<sonsNum ; i++) {
sons[i]=tmpSons[i];
}
sons[sonsNum]=sn;
sonsNum++;
}
edit:
sorry forgot to said I want the real values inside the nodes so I cant copy. ( the string in this code is just for the example... its another object in real..)
edit:
solution:
void insertSon(Node* sn) {
sn->father=this;
Node** tmpSons = new Node*[sonsNum];
for(int i=0 ; i<sonsNum ; i++) {
tmpSons[i]=sons[i];
}
if(sons)
delete[](sons);
sons = new Node*[sonsNum+1];
for(int i=0 ; i<sonsNum ; i++) {
sons[i]=tmpSons[i];
}
sons[sonsNum]=sn;
sonsNum++;
delete[](tmpSons);
}
Node** tmpSons = sons; //should be shared_ptr? but I dont want that
if(sons)
//delete[](sons); // after this line, tmpSons has garbage!
Yes, that's normal -- the contents of tmpSons will be invalidated since it's just pointing to the same memory as sons, and you're freeing its contents with operator delete[].
There's no need to involve reference counting to solve this kind of problem. Simply allocate a new array (without touching sons), copy the contents of sons to the new, bigger array, and then free the memory of sons and make sons point to the new block. The key is to not free the contents of sons until you're finished copying it to your new array. It's like you don't want to throw away that CD you're copying until after you copy it (your original version was sort of throwing it away before the copy was even made). Something like this:
void insertSon(Node* sn) {
sn->father = this;
// Create a new array and copy the old data.
Node** new_sons = new Node*[sonsNum+1];
for(int i=0; i<sonsNum; i++)
new_sons[i] = sons[i];
new_sons[sonsNum++] = sn;
// Delete old data.
delete[] sons;
// Point to the new data.
sons = new_sons;
}
That should hold you up until you start worrying about things like exception-safety, at which point you probably do want to avoid relying too much on these manual memory management techniques and use more RAII-conforming objects.
Visual Breakdown
Here's a visual breakdown. First we start with the sons pointer which points go a memory block containing some "sons" of a "father" (very patriarchal naming conventions for a nodal system, btw).
Then we allocate a new, slightly bigger memory block which will be pointed to by new_sons:
Node** new_sons = new Node*[sonsNum+1];
Next we copy the former son entries into the new array.
for(int i=0; i<sonsNum; i++)
new_sons[i] = sons[i];
... and add our new entry.
new_sons[sonsNum++] = sn;
Now that we have a copy, we can throw away the old data.
// Delete old data.
delete[] sons;
... last but not least, we can make sons point to the new data. new_sons will then go out of scope and the pointer will be destroyed as well (not the stuff it's pointing to, just the pointer), and we'll end up getting what we want (sons now pointing to a new array, one entry bigger, with both the old entries and the new entry we added).
// Point to the new data.
sons = new_sons;
... and you're done.
When you do
Node** tmpSons = sons;
it doesn't copy the actual memory itself only the pointer, which means that you have two pointers both pointing to the same memory.
If you do delete[] on one of the pointers, then the other pointer will become a stray pointer, as it now points to unallocated memory. Dereferencing any of the pointers will lead to undefined behavior
but when deleting the old Node** using delete[], even I have saved the pointers inside to another tmp array, its values will be gone! (even Node destrucor is empty! why?)
But you haven't saved the pointers inside to another array. You do that after deleting the Node**. After you've deleted something, accessing it's content will have undefined behaviour.
is there a way to do that without shared_ptr?
Sure, delete tmpSons after you've copied it's content.
I cant use list, I am restrected...
I recommend using a vector.

double free or corruption while deleting an object (another one...)

The code below move the an element to top of an array
for ( i = j; i > 0; i-- ) {
myBlk *tmp = blks[i];
blks[i] = blks[i-1];
blks[i-1] = tmp;
delete tmp;
}
as the execution reaches delete tmp, I get:
*** glibc detected *** double free or corruption (out): 0x00007fffd556ad10 ***
If I remove that statement, there is no problem. But I don't want memory to leak...
tmp is just pointing to an existing element of the array. You have not allocated tmp via new. So there is no need to delete tmp. I am assuming that the original array elements are allocated and freed in somewhere else.
Promoting comment to answer.
It seems that you are confusing a memory allocation with a pointer copy. In your loop, you are not doing any memory allocation. You are just copying a pointer - which does not allocate memory.
So you should get rid of the delete:
for ( i = j; i > 0; i-- ) {
myBlk *tmp = blks[i];
blks[i] = blks[i-1];
blks[i-1] = tmp;
}
delete is only called when there is memory allocation - which you have none of. (none inside the loop at least)
This code looks very, very odd.
My guess (based on your comment that "A pointer is created in a loop and at the end of loop, i delete that.") I suspect that the delete is superfluous.
When you call delete tmp, this frees blks[i-1], since both tmp and blks[i-1] point to the same memory. If you expect that at the end of the loop blks continues to contain valid pointers, then the delete is certainly superfluous.
You are deleting the same element every time?
You move the deleted element to what was i-1 then decrement i.

C++ array of pointer memory leaks

In my class I have a dynamically allocated array of pointers. My declaration:
array = new Elem* [size];
for (int i = 0; i < size; i++) {
array[i] = NULL;
}
So there is an array of pointers, where each pointer points to a simple Elem struct.
The main question is, how should I properly deallocate the array. If I use only:
for (int i = 0; i < size; i++) {
delete array[i];
}
Valgrind reports 1 not-freed block, which is traced to the line where 'array = new Elem* [size];' states.
On the other hand if I add to the previous code:
delete array;
Which I thought is correct, valgrind reports 0 not-freed blocks, which is perfect, BUT it reports
Mismatched free() / delete / delete []
exactly on the line where 'delete array;' is. I tried 'delete []array' too, but that's just "1 not-freed blocks" too then! If somebody could explain me the proper way it would be much appreciated.
EDIT:
So using:
for (int i = 0; i < size; i++) {
delete array[i];
}
delete[] array;
is working probably fine. It is working in one of my classes (I have two similar) the other still reports some small leak. I would think it's just a minor bug somewhere, but valgrind still points to the line where
array = new Elem* [size];
stands.
EDIT2:
I solved this as well, thank you for your exhausting contribution!!
You need:
delete [] array;
Because it's an array.
I just noticed your note that you tried this too - it's the proper thing to do so I don't know why you'd still be getting an error.
Edit: This deserves a more thorough explanation.
When you create a pointer using new, the pointer may be to a single element or an array of elements depending on the syntax you use. But the pointer type is the same in both cases! The compiler relies on you to know what the pointer points to and treat it accordingly.
Elem ** single = new Elem*; // pointer to one pointer
single[0] = new Elem; // OK
single[1] = new Elem; // runtime error, but not compile time
Elem ** array = new Elem* [2]; // pointer to array of pointers
array[0] = new Elem; // OK
array[1] = new Elem; // OK
When you delete a pointer, the destructor is called for the object it points to or for each element of the array. But since the pointer type is the same in each case, the compiler relies on you to give it the proper syntax so it knows what to do.
delete single;
delete [] array;
In your case the elements of the array are pointers also, and pointers don't have destructors. That means those pointers won't be deleted and will become memory leaks if you don't delete them first. You were correct to have a loop to delete them individually before the final delete.
You should free everything in the array (if dynamically allocated) and then free the array itself.
for (int i = 0; i < size; i++) { // only free inside if dynamically allocated - not if just storing pointers
delete array[i];
}
delete[] array; // necesarry
The syntax for deleting an array is like this:
delete[] array;
Your for loop to delete the objects pointed to by the elements of the array is fine. The deletion of the array itself is the only problem. You need both the for loop and then the delete[] to dispose of the array itself.
for (int i = 0; i < size; i++) {
delete array[i];
}
delete[] array;
I suspect that you have tried using the for loop, or the delete[], but not both together. And if when you do that you still have leaks or errors, then you would need to show us the code that allocates the pointers that are elements of the array.
Using std::vector<> instead of an array would mean that you could stop worrying about these nitty gritty details and move to higher level of abstraction.
In this case, you need both.
for (int i = 0; i < size; i++) {
delete array[i];
}
delete[] array;
You call delete exactly once for each time you called new.
Note that although you need to call delete[] array here (because you allocated it with new[]), the delete[] operator does not call the destructors on the objects pointed to by elements of the array. This is because the delete[] operator calls destructors on objects in the array, and your array contains pointers but not objects. Pointers do not themselves have destructors.