0

So I was trying to convert a BST to DLL using some given functions which I had to use. While doing that, I kept getting segmentation faults. As I tried debugging it, I finally came to this. I have written a very simple test script below.

What I knew about pointers is it is passed by reference, as in if I am changing the value/object to which the passed pointer points to, it is reflected in my original calling function.

Why is it that when I create a new Node and then pass the pointer (myf), it works, but when I just pass the pointer and create the new Node inside the function, it shows segmentation fault (myf2)?

If this is because the new node goes out of scope, check the function "myf" again. I have created a new Node which is pointed to by my original node. And the value of this is retained after the function call ends. Doesn't this too go out of scope then?

I have some basic fundamental problems with pointers it appears and this would really help. Thanks

#include<iostream>
using namespace std;

class Node
{
public:
    int val;
    Node *left;
};

void myf(Node *a)
{
    a->left = new Node();
    a->left->val = 20;
    a->val = 15;
}

void myf2(Node *a)
{
    a = new Node();
    a->val = 35;
}

int main()
{
    Node *a = NULL, *b = NULL;
    a = new Node();
    a->val = 5;
    myf(a);
    cout << "New value of a = " << a->val << endl;
    cout << "left value of a = " << a->left->val << endl;
    myf2(b);
    cout << "New value of b = " << b->val << endl;
}
3
  • where is right pointer? Commented Mar 2, 2014 at 7:16
  • Ignore the brackets I gave after Node(). Not necessary while initializing. Commented Mar 2, 2014 at 7:16
  • Hi Rikayan. This is a test code. No logic or motives whatsoever of this program. I was in the middle of a more complicated code so I wrote this test code to find what was going wrong. Please concentrate on whatever is here. Thanks. Commented Mar 2, 2014 at 7:18

4 Answers 4

1

Your problem is, your pointer isn't being set to b, to do so, you'd need to edit myf2 to something like this:

void myf2(Node **a)
{
    *a = new Node();
    (*a)->val=35;
}


And call myf2 like so:

myf2(&b);


And that should solve your problem, I believe.


Don't think of Node *b as only a pointer, think of it as an integer as well, because that's what a pointer breaks down to, an integer pointing to a space in memory.

So you pass a pointer of the pointer(an integer) to the function.

Another example would be:

void myfunction(int *i) {
    *i = 5;
}

int main(int argc, char** argv) {
    int x;
    myfunction(&x);
    cout << x << endl;
    return 0;
}

But that's using an actual integer.

Sign up to request clarification or add additional context in comments.

3 Comments

Hi David. But *a inside myf2 is basically still a pointer to an object right? How did you allocate Node to it?
@user3370135 Yes, it's a pointer, you'd allocate a Node object to *a as shown in the example. a is a pointer to the pointer, and *a is the pointer itself. (*a) = new Node();
@user3370135 I allocated node to it by passing the mem address of the pointer itself, which most operating systems is an integer, and I stored the newly allocated object into the memory of the pointer passed to the function.
0

Why is it that when I create a new Node and then pass the pointer (myf), it works,

Node *a: main() makes it point it to a block of memory, you pass that address to myf, you update the memory in that block. It works!

But when I just pass the pointer and create the new Node inside the function, it shows segmentation fault (myf2)?

Node *b: main() doesn't assign it anything, it is pointing to NULL, myf2() get just the address that is NULL, you create another pointer b (not the same as that in main() ), make it points to some block of memory, but it doesn't update what your original b in main() points to, which is still pointing to NULL. Hence SEGFAULT.

Essentially you are trying two different valid approaches, this is the right way:

Case 1.

main()
{
    Node* a = NULL;
    a = new Node();  //make 'a' point to some valid block of memory
    myf(a);    // here you are passing the address of the memory block of type Node
    cout << "New value of a = " << a->val << endl; //and this is valid since 'a' points to a valid address
}

void myf(Node *a)
{
    a->left = new Node();  
    a->left->val = 20;  // Since the address that you got here is valid, you can make changes here, and in main() Node* a is aware of this address 
    a->val = 15; 
}

Case 2.

main()
{
    Node* b = NULL;
    myf2(&b);   // here since b points to NULL, you have to send the address where this NULL is stored so that the called functon can upadte this NULL to something meaningful
    cout << "New value of b = " << b->val << endl; // this is correct, because we changed what 'b' pointed to from NULL to a valid block of memory of type 'Node'
}

void myf2(Node **a)  //It is a double pointer here because you need to update what it points to, curently it holds NULL
{
    *a = new Node();  // Make it point to a valid address, remember main() has track of 'a', 
    *a->val = 35;  // Now if you make any changes to the blok that 'a' points to, main() will have account of it
}

6 Comments

An explanation was really what I was looking for. Thanks a lot. Makes sense. But when inside myf, I am creating a new node for b->left, am I not changing the address too? Why is that getting reflected?
see the updated comment. The variable b in main and in your fn myf2 are not the same.
Hope the updated answer helps, comment if you still have doubts.
I just understood it. So basically if I am passing a pointer to b from main, a copy of that address is made and stored in the a pointer in myf. Now if I change the address itself which a points to, that doesn't get reflected back to b in my main function. However, I can change the value/object which is stored in the address a. And the address a contains a pointer to left, so if I am updating left, THAT gets updated in my main function b. That is right? Also, to overcome this, should I be passing it as David did with a pointer to the pointer? Or like Abhay using reference? Both should work fine
But which is easier to handle in general? And are there any problems with any of them? I personally feel the pointer to the pointer would be easier to handle for me.
|
0

You need to return the reference of Node *a to which you have dynamically allocated memory..

Node* myf(Node *a)

{

    a->left = new Node();

    a->left->val=20;

    a->val=15;

    return a;
}

In main ()

a = myf(a);

previously a in main() is not pointing to memory allocated in myf() function...

1 Comment

Hi Hade. Nice answer. But actually I HAVE to return a void as I am using a recursion function and there are other factors involved. I think David's answer below would work good. I totally forgot about passing by reference thing. Anyways thanks a lot for your effort.
0

Receive your Node ptr by reference as below..

void myf2(Node *&a) //<-- Notice & in function signature.

In your current code, you are passing a (Node*) by value, so, whatever changes done in the function will not reflect outside of function and accessing b->val (null ptr access) will be a segment fault

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.