views:

136

answers:

4

Hello all, I wrote a quick program which executes every statement before giving a seg fault error.

struct foo
{
    int cat;
    int * dog;
};

void bar (void * arg)
{
    printf("o hello bar\n");
    struct foo * food = (struct foo *) arg;
    printf("cat meows %i\n", food->cat);
    printf("dog barks %i\n", *(food->dog));
}
void main()
{
    int cat = 4;
    int * dog;
    dog = &cat;

    printf("cat meows %i\n", cat);
    printf("dog barks %i\n", *dog);

    struct foo * food;
    food->cat = cat;
    food->dog = dog;

    printf("cat meows %i\n", food->cat);
    printf("dog barks %i\n", *(food->dog));

    printf("time for foo!\n");
    bar(food);
    printf("begone!\n");

    cat = 5;
    printf("cat meows %i\n", cat);
    printf("dog barks %i\n", *dog);

//  return 0;
}

which gives a result of

cat meows 4
dog barks 4
cat meows 4
dog barks 4
time for foo!
o hello bar
cat meows 4
dog barks 4
begone!
cat meows 5
dog barks 5
Segmentation fault (core dumped)

I'm not really sure why it seg faults at the end? Any comments/insights are deeply appreciated.

+4  A: 

You're dereferencing a pointer to invalid memory, food.

The line:

struct foo * food;

declares food to be a pointer to a struct foo. But since you're not initializing the pointer, it's pointing to an undefined area of memory you don't own. You can either just allocate on the stack (note I've changed the type of food):

struct foo food;
food.cat = cat;
food.dog = dog;

printf("cat meows %i\n", food.cat);
printf("dog barks %i\n", *(food.dog));

printf("time for foo!\n");
bar(&food);

or use malloc (keeping the type as struct foo *):

struct foo * food = malloc(sizeof(struct foo));
if(food == NULL)
  perror("Failed to allocate food.");

Later you should free it (though in this case it doesn't matter much):

free(food);

There are other issues with the program (e.g. the void* parameter), but this addresses the memory violation.

Matthew Flaschen
if you don't mind, could you tell me about the other issues (esp the one about void * parameter because I happen to use that very frequently). Much thanks!
Fantastic Fourier
so would it bestruct foo * food = malloc(sizeof(struct foo));food = (struct foo * ) arg;in bar function?because I'm still getting seg fault.
Fantastic Fourier
oh wait dumb dumb it works. much thanks!!
Fantastic Fourier
The issue with `void *` is basically, don't use `void *` unless you have to. In this case you don't. Just use `struct foo *` as the type.
Matthew Flaschen
I'm programming a multi-threaded client-server. And I thought that threads take functions that took void * as a parameter? (function bar is the start routine for threads and struct foo is a memory block shared by threads though it doesn't show in this simplified example)
Fantastic Fourier
Yep, that's one of the cases when you do have to use `void*`.
Matthew Flaschen
+1  A: 

Well, these lines are a problem:

struct foo * food;
food->cat = cat;
food->dog = dog;

Food is a pointer which you dereference without it being assigned to anything.

struct foo food;
food.cat = cat;
food.dog = dog;

might fix things for you.

Grumdrig
A: 

You're getting undefined behavior because you didn't malloc the food struct.

Stephen
+1  A: 

You have not allocated space for a structure variable to be pointed by the variable food:

struct foo * food;

You need to do:

struct foo * food = (struct foo*) malloc(sizeof(struct foo));

also you should be deallocating this memory once you are done using it:

free(food);

Alternative you can declare food as a variable of type struct foo as:

struct foo food; // note the missing *

and then you can access the structure members using the . operator inplace of the -> operator. So

food->cat = cat;

Changes to

food.cat = cat;
codaddict