Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I have a function to insert nodes in a binary search tree. I get a crash when I try to insert a node. I use the debugger from VS and it tells me Unhandled exception thrown: write access violation.
m_father was nullptr.
Here is my function to insert:
NOD *INSERT(NOD k)
{
NOD *temp = new NOD(k);
NOD *m_father = NULL;
NOD *x = root;
while (x != NULL)
{
m_father = x;
if (m_father->m_key > x->m_key)
{
x = x->m_right_child;
}
x = x->m_left_child;
}
if (root == NULL)
root = temp;
else if (temp->m_right_child->m_key > m_father->m_key)
{
m_father->m_right_child = temp;
}
m_father->m_left_child = temp;
temp->m_father = m_father;
return 0;
}
And here is how i try to insert a node:
int temp_nod;
cin >> temp_nod;
binary_tree.INSERT(temp_nod);
else if (temp->m_right_child->m_key > m_father->m_key)
temp is copy-constructed here (is it the expected behaviour?). If it's created from a new node, m_right_child might not be assigned yet, so you try to dereference a nullptr.
I'm not sure, but you did you want to check temp key here? I don't see much reason to check child key when choosing the correct place in BST.
Also, as noted in the comments, you assign m_father->left_child always, without a condition. This happens even in an empty list, so again we try to dereference a nullptr. I suppose it should look more like this:
if (root == NULL)
root = temp;
else if (temp->m_right_child->m_key > m_father->m_key)
{
m_father->m_right_child = temp;
temp->m_father = m_father;
}
else
{
m_father->m_left_child = temp;
temp->m_father = m_father;
}
As a side note, if your function does not return anything useful, just make it void.
If root == NULL the only assignment to m_father would be NOD *m_father = NULL;, before the statement m_father->m_left_child = temp;.
EDIT: (Because if root == NULL, then x would also be NULL, so the while loop would not be executed)
EDIT2: else if (temp->m_right_child->m_key > m_father->m_key) => m_father->m_left_child = temp; - the former will not be evaluated if root == NULL, since it is an else if to an if that was true.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm trying to implement a circular doubly linked list but I keep getting a segmentation fault: 11 error (I believe it's because of the add and delete functions). I have no idea whether my code is even close, but I can't get past this error to test it properly. This is the code I have that I believe is involved:
(Circular_DLList.cc)
void Circular_DLList::add_to_tail(int a)
{
if (is_empty()) {
tail = new DLLNode(a);
tail->next = tail;
}
else {
tail->next = new DLLNode(a, tail->next);
}
}
int Circular_DLList::delete_from_tail()
{
if(!is_empty())
{
int a = tail->info;
tail = tail->prev;
tail->next = null;
return a;
}
else
{
tail = 0;
}
return a;
}
Any help would be fantastic, thanks.
One way to find a segmentation fault is by using cout statements throughout your code and compiling and running it. If the cout statement prints something to the console then the segmentation fault happens in a line after the cout statement. Keep doing this to narrow down and locate where the line with the segmentation fault is.
There is more than one problem in your code but here is one of them.
When you add the first element, you do:
tail = new DLLNode(a);
tail->next = tail;
so you leave prev equal to 0 (BTW: use nullptr instead of 0).
If you then delete the element you do:
int a = tail->info;
tail = tail->prev; // tail becomes 0
tail->next = null; // Dereference 0 cause seg fault
return a;
BTW: Your delete function should also delete the DLLNode ! Just changing pointer values isn't sufficient.
So this leads to 3 changes:
1) When adding new elements make sure to always set both nextand prev
2) Remember to delete the DLLNode created with new
3) In your delete function you need a special case for checking whether the list contains exactly one element, i.e. if (tail == tail->next) { .. delete last element .. set tail equal nullptr}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am working on a search function to search a linked list for a specific value. When it finds that value I want to output its position. I cannot seem to get past the first node without getting an error. I think something is wrong with the loops but I'm not sure what.
int NumberList::search(double num)
{
ListNode *nodePtr;
nodePtr=head;
int i=0;
while (nodePtr->value!= NULL)
{
i=i+1;
if (nodePtr->value==num)
return i;
else
nodePtr=nodePtr->next;
}
return 0;
}
Your while loop is incorect. You should be testing that nodePtr is not NULL
while (nodePtr != NULL)
{
i = i + 1;
if (nodePtr->value == num)
return i;
else
nodePtr = nodePtr->next;
}
Also this is a perfect reason to use nullptr instead of NULL when dealing with pointers. If you had use nullptr then
while (nodePtr->value!= nullptr)
Would give you a compiler error as you cannot compare a double to nullptr
I do not know how the corresponding class is defined but I think in any case the function should look the following way
int NumberList::search(double num)
{
ListNode *nodePtr = head;
int i = 0;
while ( nodePtr != NULL && nodePtr->value != num )
{
++i;
nodePtr = nodePtr->next
}
return nodePtr != NULL ? ++i : 0;
}
It is difficult to compare exactly two floating numbers. You should use a method of comparison that for example takes into account an epsilon.
Take also into account that other functions as for example the function that adds nodes to the list can also be wrong.:)
Your while loop condition should be:
while (nodePtr != NULL)
Because of this error you are likely visiting a node who's pointer is NULL And by dereferencing this you are causing undefined behavior.
You don't show the ListNode type but I'm guessing the value is a double.
while (nodePtr->value != NULL)
Here you're checking if the double is not NULL (NULL is essentially 0). But you need to test nodePtr against NULL.
Note: Consider using nullptr instead of NULL, nullptr is the type safe value for a null pointer and would have produced a compilation error.
error: invalid operands of types 'double' and 'std::nullptr_t' to binary 'operator=='
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I am trying to develop a friend function for the union of two link lists. Compiler keeps giving me an error saying that Node was not declared in this scope, as well as p,q not declared in this scope. So I added List::Node, but it is not performing the union still
const List getunion(const List&a, const List&b) {
List::Node * p=a.list;
List::Node* q=b.list;
List result;
while (q!=NULL && p!=NULL) {
if(q->value==p->value) {
result.insert(q->value);
q=q->next;
p=p->next;
}
q=q->next;
p=p->next;
}
return result;
}
void insert(int x) {
Node* tmp=new Node;
tmp->value=x;
if(list==NULL || list->value >x){
tmp->next=list;
list=tmp;
}
else {
Node *curr=list;
while (curr->next !=NULL && curr->next->value < x) {
curr=curr->next;
}
tmp->next=curr->next;
curr->next=tmp;
}
Note my insert function adds Nodes in ascending order, and I have tried it out and it does work on test cases, it's when i implement the union function that things go astray...
I take it that you fixed the compile error and now you are wondering why it doesn't work.
You're not merging these two lists correctly. The issues are:
You only insert an item if it's in both lists - that's intersection, not union.
You are advancing both pointers simultaneously.
You need to merge one or the other:
while ( q && p ) {
if( q->value < p->value ) {
result.insert(q->value);
q = q->next;
} else if( q->value > p->value ) {
result.insert(p->value);
p = p->next;
} else {
result.insert(q->value);
q = q->next;
p = p->next;
}
}
Now, once either of those list pointers reaches the end, you still need to add the remaining elements from the other. This will do the trick:
for(; q; q = q->next) result.insert(q->value);
for(; p; p = p->next) result.insert(p->value);
Make sure, also, that you have defined a copy constructor for List. It looks like you're doing your own memory allocation in there, so you must follow the Rule of Three.
Firstly, I am not sure what you code is intended to be doing.
It seems you expect the input to be 2 lists, which you step thru in parallel, constructing a third list if the corresponding values are matching.
This is more like an intersection than a union, tho its harsher than that, since it cares about position.
The insert seems to be a sorted insert.
Anyway, this part is certainly wrong:
if(q->value==p->value) {
result.insert(q->value);
q=q->next;
p=p->next;
}
Remove these q=q->next and p=p->next.
These are causing a double step, since its done inside the if statement, and outside.
Double stepping is bad, since it can take you past the end of a list, causing crashes.
Solved - Problem with constructor
Matthew Flaschen and Michael Burr pointed out the problem of the overloaded constructor of Node(int) calling Node() which doesn't work because...
Thanks guys!
I have built a program (I am debugging it) and have run into a weird problem... A `if` statement is not getting triggered when it should be... This is a school project where we must build an AVL Tree with at least one 'optimizing' feature.
I am sure and have tested that the `rdown` and `ldown` work (as the balancing factors) - the tree is not perfectly balanced. Rather it is based on the hight of the branches (i.e. - `balance()` should only return (1,0,-1) otherwise it is unbalanced.
I hope this is enough information to solve this weird problem... I have never ran into anything like this before with Microsoft Visual Studio 2010.
Node struct:
struct Node {
int data; // the data in the Node
int rdown; // the number of ellements below the node on the right side
int ldown; // the number of ellements below the node on the left side
Node * parrent; // the node's parrent
Node * lchild; // the nodes left child
Node * rchild; // the nodes right child
Node () { rdown = 0, ldown = 0; data = 0; parrent = NULL; lchild = NULL; rchild = NULL; }
Node (int dat) {rdown = 0, ldown = 0; parrent = NULL; lchild = NULL; rchild = NULL; data = dat; }
bool end() { if (lchild == NULL && rchild == NULL) return true; // check if this node is the 'end of the line' - where it doesn't
return false; } // have any children
bool goodToAdd() { if (lchild == NULL || rchild == NULL) return true; // make sture the current node has at least one spot to add
return false; } // a new node to - either lchild or rchild must be NULL
int balance() { return (ldown - rdown); } // get a balance number for the node
};
Search function that is causing the problems
Node * AVL_Tree::search(const Node * num) {
Node * tmpNode = AVL_Tree::root; // tmpNode is a place holder for the search
for (int i = 1; true; i++) { // increment int i to check for excess searching -> pervents endless loop
if (tmpNode == NULL) //****** causing problems******** // the search has reached a dead end (the data is not contained) ==> NULL
return NULL;
if (tmpNode->data == num->data) // if the data of num is the same as tmpNode the data is contained ==> Node *
return tmpNode;
// since the node has not been found yet move down the tree...
if (tmpNode->data > num->data && tmpNode->lchild != NULL) // if the data is smaller than the tmpNode move to the lchild
tmpNode = tmpNode->lchild;
else if (tmpNode->rchild != NULL) // since the node has been proven to not be = to the data to be searched for
tmpNode = tmpNode->rchild; // and it is not smaller... move to the right
if (i > (root->ldown + 1) && i > (root->rdown + 1) ) { // the while loop has searched suffecent time and has not ended
string tmp = "the search incountered a critical error... aborting..."; // to prevent an endless loop the string error
throw tmp; // is thrown (should not happen) - indicates a broken tree
}
}
}
A screen shot of the first encounter with the for loop
A screen shot of the second encounter with the for loop
If you would note in the 'Autos' tab at the bottom that all the data and the node itself's address is NULL - yet in the next screen shot it continues
The program continues!!! what?>!
I pushed F-10 (the 'go to next command' button) ... and it jumps right over the statement? why?
0xcdcdcdcd is not a NULL pointer - that value is used in the debug builds of MSVC for memory that has been allocated but not initialized.
See When and why will an OS initialise memory to 0xCD, 0xDD, etc. on malloc/free/new/delete? for more details.
The root of your problem might be in the constructor that takes an int parameter:
Node (int dat) { Node(); data = dat; }
The Node(); statement ends up doing nothing. This constructor leaves most of the members of the structure uninitialized.
tmpNode is not null in any screenshot.
It's first 0x00294820, then 0xcdcdcdcd. The second is the magic debug value for uninitialized malloced memory.
NULL, in C++, tends to be (but is not guaranteed to be) 0.
In your second/third screenshots, tmpNode = 0xcdcdcdcd, which is not NULL. 0xcdcdcdcd is the value Visual Studio gives to uninitialized variables (when running a debug release).
Make sure to initialize all all your nodes' fields:
Node* root = NULL;
or
Node* root = new Node(); //Don't forget to delete!
Setting fields to NULL is not done automatically in C++ as it is in other languages like Java and C#.
tmpNode is referencing uninitialized memory, which is generally not guaranteed to be null. For instance, the following statement does not guarantee that tmpNode is null.
Node* tmpNode; // or assignment to another uninitialized variable.
You are assigning tmpNode to root and I suspect that root is uninitialized, hence the non-null value of tmpNode. Please check your initialization of root -- I cannot comment on it as you haven't posted this specific code.
I'm learning C++ and writing a binary search tree. The following is the code I wrote for my insert method.
BSTNode * BST::Insert(const std::string & v) {
BSTNode *n = !root ? root = new BSTNode(v) : Insert_Helper(v,root);
if(n) size++;
return n;
}
BSTNode * BST::Insert_Helper(const std::string & v, BSTNode *n) {
if(!n->value.compare(v))
return NULL; // already have v
else if(n->value.compare(v) > 0) // v goes to the left
if(n->left) return Insert_Helper(v,n->left);
else return n->left = new BSTNode(v);
else // v goes to the right
if(n->right) Insert_Helper(v,n->right);
else return n->right = new BSTNode(v);
}
The bug I'm getting goes like this: It all works fine and dandy, until I try to insert a duplicate node. It doesn't add a new node, yet it increments count.
By observing in GDB, I've found that when I try to add a string that I already have, Insert_Helper works correctly and returns NULL. This value however (on my machine) is something like 0x6, which is out of bounds of course, but not 0x0 like I thought it would be. I think this causes an issue at the point where I have the if(n) statement. In this case n evaluates to true, and so increments size one more than it should.
Furthermore, at this point in my program, the nodes continue to get added correctly, but my insert function continues to return 0x6 as the address, even though they really are in valid locations in memory that I can access.
Can anyone give me any pointers as to what I might be doing wrong?
Your compiler probably should have spotted this, but this line near the end of your helper:
if(n->right) Insert_Helper(v,n->right);
You probably should return whatever Insert_Helper returns:
if(n->right) return Insert_Helper(v,n->right);
You can change if(n) size++ to if (n != NULL) size++