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;