Home > database >  How to assign value to a null pointer given as an argument to a function?
How to assign value to a null pointer given as an argument to a function?

Time:01-05

When I try to assign value to a NULL pointer I get segmentation fault. Here's the code:

#include <iostream>
using namespace std;

struct test {
    int val;
};

void insert(test* t, int value) {
    test* x = (test*)malloc(sizeof(test*));
    x->val = value;
    t = x;
}

int main() {
    test* a = NULL;
    insert(a, 5);
    cout << (a->val) << endl;
}

I was expecting it would print 5, but it doesnt. I need to assign a value to a given pointer, inside a function. How can I do that?

CodePudding user response:

This is a bug:

test* x = (test*)malloc(sizeof(test*));

Should be:

test* x = (test*)malloc(sizeof(test));

Now bringing it all home, let's return the newly allocated pointer:

test* insert(int value) {
    test* x = (test*)malloc(sizeof(test));
    x->val = value;
    return x;
}

int main() {
    test* a = insert(5);
    cout << (a->val) << endl;

    // and let's free "a" while we can
    free(a);
}

CodePudding user response:

Pointers are no different from anything else: when used as a function argument they are passed by value.

So insert(a,5) in main() passes a copy of a to the function, and the change of the argument in the function is then not visible to the caller.

So, when control returns to main(), the value a is not changed. It is still the null pointer, and evaluating a->val gives undefined behaviour.

To fix either pass by reference.

void insert(test *&t, int value)     // note the & here
{
    test* x = (test*)malloc(sizeof(*x));
    x->val = value;
    t = x;
}

int main()
{
    test* a = NULL;
    insert(a, 5);
    cout << (a->val) << endl;
}

Note, also, that I have corrected the argument passed to malloc() since you got it wrong. You passed sizeof(test *) and really needed to pass it as sizeof(test). I have used the technique of passing sizeof(*x) since that will work even if (say) you change the type of the pointer to something else.

or pass a pointer to a pointer (test **)

void insert(test **t, int value)     // note the additional * here
{
    test* x = (test*)malloc(sizeof(*x));
    x->val = value;
    *t = x;                          // note the additional * here
}

int main()
{
    test* a = NULL;
    insert(&a, 5);                   // also note the & here
    cout << (a->val) << endl;
}

Of the two options above, passing by reference (not pointer) is usually considered preferable in C . Passing a pointer to a pointer is common in C, and (mostly) discouraged in C .

More generally, it is usually preferable to use operator new and avoid malloc() entirely in C . Among other things, it eliminates the possibility (which you demonstrated) of getting an operand of sizeof wrong. So, instead of doing

test* x = (test*)malloc(sizeof(*x));

do

test* x = new test;
  • Related