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.
Related
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.
I'm new to C++ and I normally use Java, so I have a hard time to get into pointers and references. I have to do a variation of binary search tree with inner nodes and leaf nodes (only leafs contain the data).
class Node
Node *parent;
Node *left;
Node *right;
//other stuff
}
I need to implement operator<< which adds a new node with value to the tree.
//adding a node to tree
void operator<<(int value){
if(size == 0){
//stuff
} else {
Node* temp = root;
getLeaf(temp,value);
//other magic
//temp will be used to append a new node into tree,
//so it has to point to the actual node in the tree
delete temp;
}
}
The point of function getLeaf is to find a leaf (may or may not contain the desired value) and store it into temp, which needs to be accessible in the operator<< function.
int getLeaf( Node* temp, int value) const{
int depth = 0;
//goes trough all inner nodes until it finds specific leaf
while(temp->isInner()){
++depth;
if(value < temp->getValue()){ //searched value is smaller
temp = temp->getLeft(); // to left subtree
continue;
} else {
temp = temp->getRight(); //to rightsubtree
continue;
}
return depth;
}
I am really confused how to do this and what is the right combination of pointers and values. If I set
Node* temp = root;
getLeaf(temp,value);
won't root get overridden while traversing the tree in getLeaf function?
Plus I need temp to point to actual node in the tree, so I can append a new node into it.
Could you please explain?
Migrating from Java to C++ is a bit tough. Migrating from C++ to Java is equally tough. To make things easy you just need to experiment.
In C++, pointers are variables that point to the location of another variable in memory and references are pointers that syntactically behave like the variable whose address is pointed to.
When arguments are passed to a function, the function does NOT receive the original arguments but a copy of them. The work you did is implement the traversal based on the above concepts. So how does it all "magically" work?
Your function: getLeaf(Node *&temp, int value) searches the correct leaf node and assigns it to temp at which insertion is to be performed. temp here is a copy of a reference to the pointer temp(in operator <<). So when the reference temp is assigned to in getLeaf, the pointer temp in operator << it points to is modified.
If I set
Node *temp = root;
getLeaf(temp,value);
won't root get overriden while traversing the tree in getLeaf function?
Note here that temp and root are two different pointers that point to the same variable. The content of the pointers is the same, they aren't and hence root is NOT overridden, when temp is updated.
But there is a problem later on in the code. If you delete temp;, root will also be deleted at the end of insertion as delete deletes the content pointed to by the pointer. Do NOT delete a pointer that is not allocated by a new.
Provide a separate function to free the dynamically allocated memory used by the tree, and call it at the end when you are done experimenting.
So I currently have a simple struct (linkedlist) that I will be using in a HashMap:
struct Node {
std::string key, value;
Node* head;
}
I'm currently trying to dynamically allocate an array with pointers to each struct. This is what I have right now ...
Node* nodes = new Node[100]
I understand this allocates an array of 100 nodes into memory (which I will have to delete later on); however, upon iteration to try to transverse these nodes (which I an implementing as a linked list)...
for (int x = 0; x < 100; x++) {
Node current = nodes[x]; // Problem is I wanted an array to node pointers. This is not a pointer.
while (current != nullptr) { // this isn't even legal since current is not a pointer.
// DO STUFF HERE
current = current.next; // This is not a pointer access to a method. I'm looking to access next with current->next;
}
}
Hopefully I was clear enough. Can someone how to allocate a dynamic array of pointers to structs? So far I'm able to dynamically allocate an array of structs, just not an array of pointers to structs.
There are two approaches. Either you allocate an array of structures and introduce one more pointer that will point to the element in the array that will play the role of the head.
For example
Node *head = nodes;
(in this case head points to nodes[0])
After the list will not be needed you have to delete it using operator
delete [] nodes;
Or you can indeed to allocate an array of pointers to the structure like this
Node **nodes = new Node *[100];
But in this case each element of the array in turn should be a pointer to a dynamically allocated object;
And to delete the list you at first have to delete each object pointed to by elements of the array for example in a loop
for ( int i = 0; i < 100; i++ ) delete nodes[i];
and then to delete the array itself
delete [] nodes;
It is a good idea to initialize each element of the array with zeroes when the array is allocated for example
Node **nodes = new Node *[100]();
I suggested you this structure:
class myList {
struct Node {
string value;
Node* next;
}
/*Public methods .. Add/Set/Get/Next/isEmpty.. etc ... */
Node* head, *tail;
};
in main:
myList* lis = new myList[number];
then you have number of lists! and do all work in class by method's and operators, like if you want the next node just call lis[0].getNext();
if you want to skip current node dolis[0].Next(); ... etc ..
this how to work, what you try to do is looks like C program!
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.
I'm trying to make a Stack using an underlying linked list structure.
Maybe I'm wrong, but I'm having trouble with the remove() function.
int Stack::remove(){
node* victim = new node;
int popped;
popped = top->element;
victim = top;
top = victim->next;
delete victim;
return popped;
}
I'm getting glibc dectecting
double free or corruption (out);
Since I'm allocating new memory with victim, don't I have to delete victim, or is that something I don't have to worry about?
A stack is much like a bunch of dishes that are being washed and set on top of one another. That is the first one in is the last one out (FILO data type). That is if your stack read in 2, 7, 8 then it would appear as :
8
7
2
That is first the 2 is placed in the stack, followed by the 7 and then by the 8. If you want to remove or pop the stack you need to move the head of the pointer. Your code looks a bit strange to me...
int Stack::remove()
{
int datum; //to store the popped value
node* temp=head; //assign pointer to head of list
datum = temp->data; //grab the data value stored at the head (or temp since they carry same reference)
head = temp->next; //move the head pointer (in our example now it points to 7)
delete temp;
return datum;
}
There's no reason to allocate heap memory in a remove() method as you are doing with victim. What you want is:
int Stack::remove(){
node* new_top = top->next;
int popped = top->element;
delete top;
top = new_top;
return popped;
}
You don't need to allocate a node for victim. Just assign the top of the stack to it and, if it's not null, set top to its next pointer, retrieve the value from victim, and then deallocate the victim.
It's not actually a corruption, but a memory leak - you are allocating a node, and then override that pointer with victim = top; thus losing track of just allocated memory.