Click here to Skip to main content
15,912,329 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
When i use pointers to create a node in a Binary tree is gives me a segmentation error, whereas when i use double pointers it works just fine.

To me both the pieces of code seem to be pretty fine but then why doesn't the former work?

Since we are just dereferencing the pointer in the later case, why doesn't it work when i use just a pointer?


What I have tried:

This is the one which works (Double Pointers)

void Insert(struct bnode **root, int n){
    if(*root == 0){
        temp = (struct bnode *) malloc (sizeof(struct bnode));
        temp -> data = n;
        temp -> right = temp -> left = 0;
        *root = temp;
        return;
    }else{
        temp = *root;
        while(temp != 0){
            if(n >= temp -> data){
                temp = temp -> right;
            }else{
                temp = temp -> left;
            }
        }
        temp = (struct bnode *) malloc (sizeof(struct bnode));
        temp -> data = n;
        temp -> right = temp -> left = 0;
    }
}


I want to know why the code below doesn't work (Pointers)

void Insert(struct bnode *root, int n){
    if(root == 0){
        temp = (struct bnode *) malloc (sizeof(struct bnode));
        temp -> data = n;
        temp -> right = temp -> left = 0;
        root = temp;
        return;
    }else{
        temp = root;
        while(temp != 0){
            if(n >= temp -> data){
                temp = temp -> right;
            }else{
                temp = temp -> left;
            }
        }
        temp = (struct bnode *) malloc (sizeof(struct bnode));
        temp -> data = n;
        temp -> right = temp -> left = 0;
    }
}
Posted
Updated 27-Mar-17 8:37am
v2
Comments
Member 13037163 27-Mar-17 11:42am    
P.S - I know the functionality of my code is wrong but I just need to know the reason behind this behavior.
Jochen Arndt 27-Mar-17 11:58am    
This can't be answered without seeing the complete code (how Insert() is called and with which root argument).
Member 13037163 27-Mar-17 12:00pm    
Insert(root, num);
In former case (Pointer)
Insert(&root, num);
In later case (Double Pointer)
Patrice T 27-Mar-17 14:35pm    
Use Improve question to update your question.
So that everyone can pay attention to this information.

Compiling does not mean your code is right! :laugh:
Think of the development process as writing an email: compiling successfully means that you wrote the email in the right language - English, rather than German for example - not that the email contained the message you wanted to send.

So now you enter the second stage of development (in reality it's the fourth or fifth, but you'll come to the earlier stages later): Testing and Debugging.

Start by looking at what it does do, and how that differs from what you wanted. This is important, because it give you information as to why it's doing it. For example, if a program is intended to let the user enter a number and it doubles it and prints the answer, then if the input / output was like this:
Input   Expected output    Actual output
  1            2                 1
  2            4                 4
  3            6                 9
  4            8                16
Then it's fairly obvious that the problem is with the bit which doubles it - it's not adding itself to itself, or multiplying it by 2, it's multiplying it by itself and returning the square of the input.
So with that, you can look at the code and it's obvious that it's somewhere here:
C#
private int Double(int value)
   {
   return value * value;
   }

Once you have an idea what might be going wrong, start using teh debugger to find out why. Put a breakpoint on your line:
C#
if(root == 0){

and run your app. Think about what each line in the code should do before you execute it, and compare that to what it actually did when you use the "Step over" button to execute each line in turn. Did it do what you expect? If so, move on to the next line.
If not, why not? How does it differ?

This is a skill, and it's one which is well worth developing as it helps you in the real world as well as in development. And like all skills, it only improves by use!

Yes, I could probably tell you what "the problem" is - but it's not difficult to do this yourself, and you will learn something really worthwhile at the same time!
 
Share this answer
 
Comments
Member 13037163 27-Mar-17 12:11pm    
Thank you so much for this useful tip. I certainly will look into it and try to identify the problem.
Although I did use a debugger and the error occurred when I tried to print out the data in the root node.
OriginalGriff 27-Mar-17 12:23pm    
"the error occurred when I tried to print out the data in the root node."
That doesn't tell you much - all it means is "the value was corrupted after I inserted a value". You need to know where it was corrupted - and stepping through in the debugger will tell you that. Once you know where, it should be pretty simple to find out why!
Member 13037163 27-Mar-17 12:24pm    
I'll do that and get back with the results. Thanks again!
OriginalGriff 27-Mar-17 12:31pm    
You're welcome!
You did not show us the complete code but it should be something like
C++
typedef struct bnode {
    int data;
    bnode *left;
    bnode *right;
};

bnode *root = NULL;

Then use the Insert(bnode **root) version because only that will update the global root here
*root = temp;
The single pointer version will assign temp to the local variable root (the passed argument) but not update the global one.

Why you got a segmentation fault can't be answered without seeing the full code. But I guess that you did not check if your global root is still NULL after calling Insert. And that is the case when using the single pointer version.
 
Share this answer
 
Comments
Member 13037163 27-Mar-17 14:40pm    
Yes I understood what the problem was. Thank you so much.
Simply put, C parameters are always passed by value, so, if you need to change an external variable value inside a function then you have to pass the address of such variable to the function.
Since you need to change the value of root inside the Insert function then you have to pass the its address, namely &root. This establishes the correct signature of the Insert function.
Try, for instance:
C
#include <stdio.h>
#include <stdlib.h>

void allocate_1(int * p)
{
  p = malloc(sizeof(int));
  *p = 1;
}

void allocate_2(int ** pp)
{
  *pp = malloc(sizeof(int));
  **pp = 2;
}

int main()
{
  int * p;


  // allocate_1
  p = NULL;

  allocate_1( p );

  printf("after allocate_1: p = %p", p);

  if ( p )
  {
    printf(", *p = %d", *p);
    free(p);
  }
  printf("\n");


  // allocate_2
  p = NULL;

  allocate_2( &p );

  printf("after allocate_2: p = %p", p);

  if ( p )
  {
    printf(", *p = %d", *p);
    free(p);
  }
  printf("\n");


  return 0;
}

output:
after allocate_1: p = (nil)
after allocate_2: p = 0x13f7440, *p = 2
 
Share this answer
 
v4
Comments
Member 13037163 27-Mar-17 13:03pm    
I guess that answered my question. Thanks alot!
CPallini 27-Mar-17 13:20pm    
You are welcome.
When you don't understand what your code is doing or why it does what it does, the answer is debugger.
Use the debugger to see what your code is doing. Just set a breakpoint and see your code performing, the debugger allow you to execute lines 1 by 1 and to inspect variables as it execute, it is an incredible learning tool.

Debugger - Wikipedia, the free encyclopedia[^]
Mastering Debugging in Visual Studio 2010 - A Beginner's Guide[^]
Basic Debugging with Visual Studio 2010 - YouTube[^]

The debugger is here to show you what your code is doing and your task is to compare with what it should do.
There is no magic in the debugger, it don't find bugs, it just help you to. When the code don't do what is expected, you are close to a bug.
 
Share this answer
 
Comments
Member 13037163 27-Mar-17 14:39pm    
Thanks for the advice. I will look into it for sure.
Patrice T 27-Mar-17 14:43pm    
For more help, update your question with complete code (enough to compile)
Member 13037163 27-Mar-17 14:45pm    
I think the fact that I change the value of root in the function requires me to pass the address of root rather than root itself since it is a global variable. Passing root makes it a local variable and makes the main function unable to access it without errors.

Hope I am right about this. Am I?
Patrice T 27-Mar-17 14:51pm    
Can't tell without seeing a piece of code that compile.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900