Reputation: 77
Ok, so i'm totally new to structs in c, and i have a problem that seems very strange to me.
When passing a simple struct to a function using it's pointer, the struct automatically takes one of the other arguments of that function as it's new data. I have no idea why this would happen..
At this moment move_walker() should do nothing at all, right?
typedef struct {
int x,
y;
} walker_t;
walker_t* init_walker(int x, int y) {
walker_t walker;
walker.x = x;
walker.y = y;
walker_t *pointer = malloc(sizeof(walker));
pointer = &walker;
return pointer;
}
int move_walker(walker_t * walker, int direction) {
return 0;
}
walker_t* walker;
walker = init_walker(8,2);
printf("%d %d\n", walker->x, walker->y); //will print '8 2'
move_walker(walker, 3);
printf("%d %d\n", walker->x, walker->y); //will print '0 3'
(I'm pretty sure that it doesnt matter, but this code is actually spreaded over multiple files.)
Upvotes: 2
Views: 165
Reputation: 19153
Your init_walker
is wrong, because it returns a pointer to a stack-local variable, walker
. That variable's memory gets reclaimed once init_walker
exits. Your first printf
still works, sort of by accident, because your walker
variable's value is still untouched on the stack. As soon as you make any function call after that, however, the stack frame of your original init_walker
call gets overwritten, and the walker
pointer is now pointing to some random garbage.
When you malloc
inside init_walker
, you're already allocating memory on the heap (which, unlike the stack, lives beyond the lifetime of a stack frame) for your walker_t
. So, you should do this instead:
walker_t* init_walker(int x, int y) {
walker_t *pointer = malloc(sizeof(walker_t));
pointer->x = x;
pointer->y = y;
return pointer;
}
Upvotes: 3
Reputation: 213842
...or, after a sanity check of the code, you could as well write:
typedef struct
{
int x,
int y;
} walker_t;
void init_walker(walker_t* obj, int x, int y)
{
obj->x = x;
obj->y = y;
}
walker_t walker;
init_walker(&walker, 8,2);
Upvotes: 0
Reputation: 13207
You are creating your struct-object on the stack. You'll need to allocate it using
walker_t* init_walker(int x, int y) {
walker_t* walker = malloc(sizeof(walker_t));
...
return walker;
}
With
walker_t *pointer = malloc(sizeof(walker));
pointer = &walker;
you are creating a memory-leak! You assign new memory to *pointer and lose the pointer when you assign &walker to pointer.
Upvotes: 2
Reputation: 945
your code is to put it polity 'very strange'.
This will work better...
walker_t *init_walker (int x, int y)
{
walker_t *p_walker = (walker_t *)malloc (sizeof(walker));
if (p_walker != NULL)
{
p_walker->x = x;
p_walker->y = y;
}
return (p_walker);
}
Then call free (walker)
when you've finished with them
Upvotes: 0
Reputation: 3571
walker_t* init_walker(int x, int y) {
walker_t walker;
walker.x = x;
walker.y = y;
walker_t *pointer = malloc(sizeof(walker));
*pointer = walker; /* here was the error. Copy the value not the adress */
return pointer;
}
But it can be simpler:
walker_t* init_walker(int x, int y) {
walker_t *pointer = malloc(sizeof(*pointer));
pointer->x = x;
pointer->y = y;
return pointer;
}
Upvotes: 0
Reputation: 3821
The problem is that your walker
pointer goes to invalid stack memory, because init_walker
has a bug: You create a walker_t
struct on the stack, then reserve memory with malloc
and assign the address of that memory to pointer
. So far so good.
However, the line pointer = &walker
does not copy the struct from the stack to the new memory, instead it makes pointer
point to your struct on the stack! &walker
is the address of walker
, and you assign that to your pointer. What you probably want to do is to copy the struct. To do that, you have to dereference your pointer:
*pointer = walker
That should make your program work as intended. You can also skip the struct on the stack completely:
walker_t* init_walker(int x, int y) {
walker_t *walker = malloc(sizeof(walker_t));
walker->x = x;
walker->y = y;
return walker;
}
Upvotes: 3