I have a problem with this very simple block of code. please give me your advice .
(My this problem is solved, and in solving this problem the person having id stakx really helped me, the only problem was that i was using stack< treeNode >, when i saw the push method of the stack carefully, there is a copying process when i write head->object=number, so finally i made the stack of pointers, like this stack< treeNode* > and it really solved the problem , i have no problem now , i am very very thankful to the person stakx.)
before the code you need to suppse the following tree
alt text http://img44.imageshack.us/img44/7016/avlimage06.jpg
as you can see in the picture that root is 8 and stack have two nodes i.e 6 and 4. i pass this stack and root node to the following code
void Avltree::attachwithtree(treeNode* tree, Stack<treeNode>&s)
{
if(!s.isempty())
{
treeNode *stacknode;
stacknode=s.pop();
cout<<"\ninside the attachwithtree function, stack node is "<<stacknode->data;
stacknode->right=tree;//attaching the passed node to the right of popped node
root=stacknode;//setting the root to stack node which is the private data member of class
updatebalance(root);//this function is ok, it does not create problem
while(!s.isempty())
{
cout<<"\nstack is still not empty";
stacknode=s.pop();
cout<<"\nright side of "<<root->data<<" is "<<(root->right)->data;
//the below three lines causing the problem i don't know why,
root=stacknode;
treeNode* temp;
temp=root->right;
cout<<"\n\n\nthe right side of "<<temp->data<<" is now "<<(temp->right)->data;
updatebalance(root);
}
the ouptput of this function is given by
here is the code of the pop method of the stack that i am using
template <class t>
t * Stack<t>::pop()
{
if(topelement!=NULL)
{
t* num;
current=topelement;
num=&(current->object);
topelement=topelement->preptr;
current=topelement;
return(num);
}
else
{
head=NULL;
}
}
here is the code of push method of the stack
template <class t>
void Stack<t>::push(t &number)
{
Node<t>* newNode=new Node<t>;
if(head==NULL)
{
head=newNode;
topelement=newNode;
current=newNode;
head->object=number;
head->preptr=NULL;
}
else
{
topelement=newNode;
newNode->preptr=current;
current=topelement;
newNode->object=number;
}
}
Original answer:
Could it be that the node 4 on the stack has a different node 6 to its right (the one with node 7 to its right) than the node 6 (with the node 8 on its right) you're working on? You could compare their addresses to make sure you haven't got two different copies of node 6 around.
Elaboration on the above argument:
Let's look at your method's signature:
void Avltree::attachwithtree(treeNode* tree, Stack<treeNode>&s)
s is defined as a reference to a Stack<treeNode>.
Could it be that it should be a Stack<treeNode*>?
Depending on your treeNode class, it's possible that when you push X on this stack, you actually end up with a copy of X and not X itself. Similarly, when you pop from the stack, you might not actually get the item you pushed, but an identical-looking copy of it!?
This would mean that, at the time when you push node 6 on the stack, its right child is node 7. But you have pushed a new, identical node on the stack. Even if you pop this element from the stack and change it, you only change a copy and leave the original tree node as it was before.
Therefore, you'd operate on different copies of node 6. First, you pop a copy of it from the stack, and append a tree as its right child. Checking this will give the right result.
Then, you pop a copy of node 4 from the stack. It's right child is node 6, as expected, BUT not the one you just modified but the original! Therefore you get 7 on the right side of node 6.
Demonstrating the difference between pass-by-value and pass-by-reference:
OK, here's something you need to understand when working with pointers or references. It basically shows the difference between passing a parameter by value (a copy will be created) or passing it by reference (no copy will be created).
Study it carefully and then see how it applies to your problem.
#include <iostream>
class someObject
{
private:
int _value;
public:
someObject(int value) : _value(value) { }
int getValue()
{
return _value;
}
};
void someFunction(someObject objCopy, someObject* objPtr)
{
std::cout << "objCopy.getValue() -> " << objCopy.getValue() << std::endl;
std::cout << "objPtr->getValue() -> " << objPtr->getValue() << std::endl;
if ( &objCopy != objPtr )
{
std::cout << "objCopy is not actually *objPtr but a copy of it." << std::endl;
}
else
{
std::cout << "objCopy and *objPtr are one and the same object." << std::endl;
}
}
int main()
{
someObject X(17);
someFunction(X, &X);
return 0;
}
Hint: Yes, in your pop method, you work with pointers, but most likely with a pointer to a copy of the object originally pushed on the stack.
Is that your own Stack class? A quick look at the STL tells me that pop() has return type void.
It could be that stakx is onto something here. If your pop() function returns a copy of the top element rather than a reference to it, the changes you make will only apply to the copy. Do you explicitly add the copy back into the tree anywhere after modifying it?
Related
This question already has answers here:
What's the difference between passing by reference vs. passing by value?
(18 answers)
Closed 3 days ago.
I have a method called deleteList that takes a head of a single linked list as an input and it removes all the nodes.
In the method deleteList I can verify that all the nodes are deleted, but when the execution returns back to the main, myList is not empty. So in the subsequent call to LengthOfList, the code fails with an exception.
[Please note that I am unable to change the signature of deleteList]
Here is the code:
#include <iostream>
using namespace std;
typedef struct CodeNode* List;
struct CodeNode
{
char data;
List next;
CodeNode(char new_data, List new_next)
: data(new_data), next(new_next) {
}
};
int LengthOfList(List head)
{
int len = 0;
for (List ptr = head; ptr != nullptr; ptr = ptr->next) {
len++;
}
return len;
}
void deleteList(List head)
{
List prev = head;
while (head)
{
head = head->next;
delete(prev);
prev = head;
}
// I can verify that head is null and all the nodes have been deleted
}
int main(void)
{
List temp1 = new CodeNode('3', nullptr);
List temp2 = new CodeNode('2', temp1);
List myList = new CodeNode('1', temp2);
cout << "Before " << LengthOfList(myList);
deleteList(myList);
cout << "After " << LengthOfList(myList); // CODE FAILS HERE because myList is pointing to a bad memory address (it SHOULD be NULL)
}
Pass by reference
void deleteList(List& head)
The & makes all the difference. If you want a function to alter a variable in the calling function then you pass by reference.
All your code is doing is modifying the variable head in the function deleteList which is not the same variable as head in main. By using a reference you make head in deleteList an alias for the variable used in the calling function, and therefore changes to it effect that variable.
Another option is to return the changed variable, so in main
myList = deleteList(myList);
and in deleteList
List deleteList(List head)
{
...
return head; // return modified head
}
Both approaches work, it's a style choice which you choose.
I just noticed your comment, 'please note I'm unable to change the signature of deleteList'. Then I'm afraid your code is guaranteed to fail. There is no solution given the peculiar constraints you have been given.
It's amazing how often we see this here, newbie struggling with some problem, but unable to use any of the solutions that any normal programmer would use because of artificial constraints placed on the task by their teacher. In some cases, like yours, these constraints are so severe that there is literally no solution to the task that they've been given. I suggest you ask your teacher for some advice.
In short, your solution is doing exactly this.
#include <iostream>
typedef struct CodeNode* List;
struct CodeNode {
char data;
List next;
CodeNode(char new_data, List new_next): data(new_data), next(new_next) {}
};
int main() {
List myList = new CodeNode('1', nullptr);
cout<<myList->data<<endl;
delete(myList);
cout<<myList->data<<endl;
return 0;
}
// given error
// AddressSanitizer: heap-use-after-free on address
// 0x602000000010 at pc 0x000000342fd6 bp 0x7fffcb6b5110 sp 0x7fffcb6b5108
And, accessing myList after deletion is supposed to be undefined as this is an example of heap use after free which occurs when a program continues to use a pointer after it has been freed.
Useful Links
ASAN heap use after free
Use after free error?
Solution
john's answer has already given the answer on how passing by reference can actually update the underlying variable and produce the desired effect.
I just wanted to supplement the reason for your understanding.
I wrote a program to create a linked list, and I got undefined behavior (or I assume I did, given the program just stopped without any error) when I increased the size of the list to a certain degree and, critically, attempted to delete it (through ending its scope). A basic version of the code is below:
#include <iostream>
#include <memory>
template<typename T> struct Nodeptr;
template<class T>
struct Node {
Nodeptr<T> next;
T data;
Node(const T& data) : data(data) { }
};
template<class T>
struct Nodeptr : public std::shared_ptr<Node<T>> {
Nodeptr() : std::shared_ptr<Node<T>>(nullptr) { }
Nodeptr(const T& data) : std::shared_ptr<Node<T>>(new Node<T>(data)) { }
};
template<class T>
struct LinkedList {
Nodeptr<T> head;
void prepend(const T& data) {
auto new_head = Nodeptr<T>(data);
new_head->next = head;
head = new_head;
}
};
int main() {
int iterations = 10000;
{
LinkedList<float> ls;
std::cout << "START\n";
for(float k = 0.0f; k < iterations; k++) {
ls.prepend(k);
}
std::cout << "COMPLETE\n";
}
std::cout << "DONE\n";
return 0;
}
Right now, when the code is run, START and COMPLETE are printed, while DONE is not. The program exits prior without an error (for some reason).
When I decrease the variable to, say, 5000 instead of 10000, it works just fine and DONE is printed. When I delete the curly braces around the LinkedList declaration/testing block (taking it out its smaller scope, causing it NOT to be deleted before DONE is printed), then everything works fine and DONE is printed. Therefore, the error must be arising because of the deletion process, and specifically because of the volume of things being deleted. There is, however, no error message telling me that there is no more space left in the heap, and 10000 floats seems like awfully little to be filling up the heap anyhow. Any help would be appreciated!
Solved! It now works directly off of heap pointers, and I changed Node's destructor to prevent recursive calls to it:
~Node() {
if(!next) return;
Node* ptr = next;
Node* temp = nullptr;
while(ptr) {
temp = ptr->next;
ptr->next = nullptr;
delete ptr;
ptr = temp;
}
}
It is a stack overflow caused by recursive destructor calls.
This is a common issue with smart pointers one should be aware of when writing any deeply-nested data structure.
You need to an explicit destructor for Node removing elements iteratively by reseting the smart pointers starting from the tail of the list. Also follow the rule-of-3/5 and do the same for all other operations that might destroy nodes recursively as well.
Because this is essentially rewriting all object destruction it does however make use of smart pointers in the first place somewhat questionable, although there is still some benefit in preventing double delete (and leak) mistakes. Therefore it is common to simply not use smart pointers in such a situation at all and instead fall back to raw pointers and manual lifetime management for the data structure's nodes.
Also, there is no need to use std::shared_ptr here in any case. There is only one owner per node. It should be std::unique_ptr. std::shared_ptr has a very significant performance impact and also has the issue of potentially causing leaks if circular references are formed (whether intentionally or not).
I also don't see any point in having Nodeptr as a separate class. It seems to be used to just be an alias for std::make_shared<Node>, which can be achieved by just using a function instead. Especially inheriting from a standard library smart pointer seems dubious. If at all I would use composition instead.
Hello everyone i wish you are having a great day, i have a problem with allocation memory for my tree with some code i think it's easier to explain and understand.
#define H 7
class Node{
public:
int node_number;
int depth;
int value;
Node* nodes[L];
public:
Node new_node(int node_number,int depth,int value);
void add_node(Node root_node,Node new_node);
void print_node(Node print_node);
};
To create a node my function is here
Node Node::new_node(int node_number,int depth,int value){
Node x;
x.node_number=node_number;
x.depth=depth;
x.value=value;
x.nodes[L]=(Node*) std::malloc(L*sizeof(Node));
return x;
}
and now when i want to add nodes in the node him self like declared in the class i got Segmentation fault (core dumped)
void Node::add_node(Node root_node,Node new_node){
root_node.nodes[0]=&(new_node);
}
My main function
Node root_node;
root_node=root_node.new_node(10,2,23);
Node x;
x=x.new_node(17,19,7);
root_node.add_node(root_node,x);
root_node.print_node(root_node);
Thank you so much
There are few problems here. Firstly you're not actually allocating any new memory. The line in the new_node method
Node x;
is a local variable so it will be destroyed when the method completes, the method then returns a copy of this object on the stack.
Then in the add_node method there is another problem:
root_node.nodes[0]=&(new_node);
This line doesn't call the node_node method, it actually takes the address of the function. Even if it did call the method it would be returning a copy of the object on the stack not a pointer to an object on the heap which is what you need.
Your code doesn't show the definition of L, I'm going to assume that it is a macro definition. Your new_node method should look like this, node the new reserved word, this is where the new object is created on the heap:
Node* Node::new_node(int node_number,int depth,int value){
Node *x = new Node;
x->node_number=node_number;
x->depth=depth;
x->value=value;
// x->nodes[L]=(Node*) std::malloc(L*sizeof(Node));
// not needed if L is a macro and needs correcting if L is a variable
return x;
}
Now this method returns a pointer to a new object on the heap.
Your add_node method will then look like this:
void Node::add_node(Node root_node,Node new_node){
root_node.nodes[0]=new_node(/* Need to add params here! */);
}
However there is a much better way of doing what you want here. You should write a constructor for the Node class like below:
Node::Node(int node_number,int depth,int value)
{
this->node_number = node_number;
this->depth = depth;
this->value = value;
}
This removes the need for the new_node method and means your add_node method will look like this:
void Node::add_node(Node root_node,Node new_node){
root_node.nodes[0]=new Node(/* Need to add params here! */);
}
Hope this helps.
Although there is already a complete answer provided by PeteBlackerThe3rd, I deem it worthy to also provide an answer that does not use any manual memory allocation as this is often the preferred way in C++.
I took the liberty to make some minor adjustments, e.g., when adding a node it is not necessary to provide the depth in the tree as this can be derived from its parent's node.
The struct uses a std::vector which has (at least) two benefits compared to the code provided in the question. First, there is no need to know the maximum number of children nodes during compile time. If you want to fix this during compile time one can easily replace the std::vector by std::array. Second, there is no need to manually free memory at destruction as this is all taken care of by std::vector.
#include <iomanip>
#include <vector>
struct Node
{
// I expect these data members to be constants
int const d_nodeNumber;
int const d_depth;
int const d_value;
std::vector<Node> d_childNodes;
Node() = delete;
Node(int number, int depth, int value)
:
d_nodeNumber (number),
d_depth (depth),
d_value (value),
d_childNodes ()
{ }
/*
* Note that this function does not ask for a 'depth' argument
* As the depth of a child is always the depth of its parent + 1
*/
void addChildNode (int number, int value)
{
d_childNodes.emplace_back(number, d_depth + 1, value);
}
/*
* Just an arbitrarily function to generate some output
*/
void showTreeFromHere() const
{
int const n = 1 + 2 * d_depth;
std::cout << std::setw(n) << ' '
<< std::setw(5) << d_nodeNumber
<< std::setw(5) << d_depth
<< std::setw(5) << d_value << std::endl;
for (Node const &n: d_childNodes)
n.showTreeFromHere();
}
};
The struct can be used as follows:
int main()
{
Node root_node(0,0,0);
// Add two child nodes
root_node.addChildNode(1,1);
root_node.addChildNode(2,1);
// Add six grandchildren
root_node.d_childNodes[0].addChildNode(3,8);
root_node.d_childNodes[0].addChildNode(4,8);
root_node.d_childNodes[0].addChildNode(5,8);
root_node.d_childNodes[1].addChildNode(6,8);
root_node.d_childNodes[1].addChildNode(7,8);
root_node.d_childNodes[1].addChildNode(8,8);
root_node.showTreeFromHere();
}
I'm creating a small AVL tree class in C++, and I'm getting a bit mixed up with pointers here, and its acting rather strangely.
In the class, I have a variable named "root", which is a pointer to a node. At one point, I pass a pointer of this object into the following function:
template <class T> void AVL<T>::RRotate(Node ** node) {
std::cout << this->root << std::endl << *node << std::endl;
*node = (*node)->left;
std::cout << this->root << std::endl << *node;
}
(Note that 'left' is a field that contains a pointer to a node).
Now, the first print is always printing out the same memory location.
However, the second call will print a different directory for this->root and *node.
Why is this? When I set "*node = (*node)->left;", shouldn't it be changing this->root too, since node is just a pointer to that pointer?
I'm a tad confused.
Any help is appreciated!
EDIT: A sample output is as follows:
0x902a88
0x902a88
0x902a88
0x902aa8
EDIT 2: Printing out &this->root and node instead reveals that they're always the same value, so it looks like the pointer is pointing to the right place.
You should call RRotate(&root) if you want node to be a pointer to this->root.
Or, more detailed:
node = &(this->root);
this->RRotate(node);
Most likely, in your code node just doesn't point to the root field. Try printing node and &root.
I am working on some binary tree algorithms and need a "find node with searchindex..." function. The design for treenodes is basically
class TreeNode {
int index; // some identifier
TreeNode *left;
TreeNode *right;
}
and a tree is defined by a pointer to the root-node.
My implementation for the search function is:
void Tree::searchNode(TreeNode * root, int nodeIndex, TreeNode *resultNode){
/* Recursive search */
if (root->index == nodeIndex) {
resultNode = root;
} else {
/* search children if the current node is not a leaf */
if(!root->isLeaf()) {
this->searchNode(root->left,nodeIndex,resultNode);
this->searchNode(root->right,nodeIndex,resultNode);
}
}
}
Arguments: *root is the root-node of the tree, nodeIndex is the search-index and *resultNode is the pointer to the found (or not) node in the tree.
The function does not return a reference or pointer to the found node but modifies the pointer resultNode so it points to the found node. The idea is to initialize resultNode with NULL, perform the search and modify it if a match occurs. Otherwise it remains NULL and I can easily check if there are search results or not.
Another class with a tree buildingTree as member utilizes the search-function in this way:
TreeNode *resultNodePtr = NULL;
this->buildingTree->searchNode(this->buildingTree->rootPtr,
currentNodeIndex, resultNodePtr);
// do sth. with resultNodePtr if != NULL
I create *resultNodePtr on the stack because I just need it temporarily inside the function. Is this done correctly? However: The function does not work. resultNodePtr is always NULL, even if the tree contains a node with the search-index. I debugged it very carefully step by step, it detects
(root->index == nodeIndex)
correctly but
resultNode = root;
does not work (I want resultNode to point to the same adress root points to).
Debugger says resultNode before assignment is 0x0, root node is some adress, after the assignment resultNode remains 0x0.
Do I have to overload the operator= in this case for the class TreeNode?
I have tried it:
TreeNode & TreeNode::operator=(const TreeNode & oldTreeNode){
*this = oldTreeNode;
return *this;
// ignore childs for now
}
I am not an expert but this operator= seems trivial. Does it affect the assignment of two TreeNode pointers *node1 = *node2 at all?
Maybe you can help me. Thanks for reading, appreciate your help.
If I find a solution myself I will post it here.
Regards,
Mark
Because you pass resultNode into the function as a pointer by value, its original value never changes. Think of TreeNode* as literally nothing more than a number representing a memory address; when you reassign it:
resultNode = root;
This modifies the copy that searchNode has, but not the original pointer in the code which invokes searchNode. Take this simpler example:
void Foo(int x)
{
x = 100;
}
void Bar()
{
int x = 0;
Foo(x);
// at this point, x is still 0
}
resultNode's value doesn't change from NULL for the same reason that x doesn't change from 0 when the function Bar is invoked. To fix this issue, pass the pointer in as a pointer to a pointer, or a pointer by reference:
void Tree::searchNode(TreeNode* root, int nodeIndex, TreeNode*& resultNode)
{
// same code
}
... or:
void Tree::searchNode(TreeNode* root, int nodeIndex, TreeNode** resultNodePtr)
{
// assign to *resultNodePtr instead
}
Your resultNode pointer is being passed by value, not by reference. So when the function call completes the pointer on the calling side does not receive a value.
Your algorithm looks fine :)