Reputation: 257
I've a small background in C that I'm trying to dig up, and I encountered something I can't explain.
Let's say I have the following structure:
struct World {
Things* things;
};
and the following functions:
void initWorld(World *world);
void addThingToWorld(World *world, Thing *thing);
Now, depending on the implementation of initWorld
and how I use it, it will either work or not. But I don't understand why the second implementation should fail. Both implementations are below:
void initWorld(World *world){
world->things = NULL;
}
// usage
World world;
initWorld(&world);
// will work, because world has been correctly initialized.
addThingToWorld(&world, &something);
void initWorld(World *world){
world = (World*) malloc(sizeof(World));
world->things = NULL; // here it does not work! things is not changed to 0x0 :(
}
// usage
World *world;
initWorld(world);
// this will crash as a side-effect of the failed world initialization (world->things has not been correctly set to NULL)
addThingToWorld(world, &something);
Thank you for your help, and correct any nonsense I might be doing, my C background is pretty poor at the moment :)
Okay I understood the fact that I was passing a pointer to my function in the second case, and re-assigning it with a local malloc so in the end the caller's variable was not changed. However as I was debugging there is still something I don't understand. In the initWorld
function, the second case, the world->things
value did not change after the assignation to NULL. I also tried to rename the local variable world to "w", I thought that maybe the debugger was displaying the caller's variable "world", but no, w->things
still was not correctly initialized to NULL.
Any hints?
Upvotes: 0
Views: 965
Reputation: 122383
A pointer is like other types, it's passed by value as function parameter. You allocated memory for the (local) parameter world
in the function, but this doesn't affect world
in the called function. This causes memory leak, by the way.
Instead, use a pointer to a pointer:
void initWorld(World **world){
*world = malloc(sizeof(World));
(*world)->things = NULL;
}
And call it:
World *world;
initWorld(&world);
Upvotes: 1
Reputation: 29116
In your examples, world
is a pointer to World
: The things it points to can be altered, but the pointer itself cannot.
You could pass a pointer to pointer to World
to solve this, but I would prefer to return a pointer if you do allocation inside a function:
World *newWorld()
{
World *world = malloc(sizeof(*world));
if (world) world->things = NULL;
return world;
}
and use it like this:
World *world = newWorld();
Upvotes: 1