joumvaer92
joumvaer92

Reputation: 252

No segmentation fault with fork

This code makes a segmentation fault:

int main(int argc, char *argv[]){
    int *n; 
    *n = atoi(argv[1]);
    printf("n: %d \n", *n);
    return 0;
}

while this works:

int main(int argc, char *argv[]){
   int *n; 
   *n = atoi(argv[1]);
   pid_t pid = fork();
   if (pid == 0)
     return 0;
   else
     printf("n: %d \n", *n);
   return 0;
}

Why the second with the fork works? I know that after int *n, I should allocate space for an int with a malloc(), but using the fork() seems to do this automatically.

edit: Now I understand Undefined behavior :) But now I'm asking: what is the cause in this specific case?

Upvotes: 5

Views: 653

Answers (4)

santiago92
santiago92

Reputation: 297

it happens that you do not see the segfault as when running fork and returns 0, your code never runs printf ("% d", *n)

The segmentation foult occurs when you try to access a memory location that is not allowed, so the solution is to assign ana memory through malloc or calloc functions, otherwise still have the problem. Try this:

 n=malloc(sizeof(int));
 *n=atoi(argv[1]);

Greetings

Upvotes: 0

Sourav Ghosh
Sourav Ghosh

Reputation: 134326

Both your code snippets invoke undefined behaviour, courtesy,

  1. using uninitialised and invalid memory *n
  2. (maybe) using uninitialised and invalid memory argv[1] (if argc is not >=2)

Segmentation fault is one of the many side-effects of UB. UB case includes working seamlessly scenario, too.

Why the second with the fork works?

It has nothing to do with presence (or absence) of fork() UB. TL;DR.

but using the fork() seems to do this automatically.

Visuals can be deceptive. Don't put your money on UB.

Upvotes: 4

dbush
dbush

Reputation: 223872

Because n is uninitialized and therefore pointing to an unknown memory address, you are invoking undefined behavior. It might crash (as in the first example), or it might not (as in the second example).

In a situation like this something as simple as adding an unused variable can make a program crash that wasn't before, or vice versa.

Allocate memory for n, and you won't have that problem.

Edit:

The fact that running ./test 100 works when you run the second program, no matter how many times, is a matter of luck. The fact that you added a call to fork (in this case) just so happened to rearrange the way memory is laid out so that it would work. Later on you might decide to a a call to printf for extra debugging and all of a sudden it starts crashing again.

Adding the fork call didn't automatically allocate any space.

The only way to prevent a crash is to allocate memory for n, and to ensure that argc is at least 2 so that argv[1] points to someplace meaningful.

Upvotes: 3

Soren
Soren

Reputation: 14688

It does not work. (Or more precisely, you have undefined behavior)

1) The fork is just hiding the segfault, because you are not checking the exit code of the child process.

2) The allocation of memory is not automatic -- ever !

You are just writing to a random location, and you may just be "lucky" that in the second version that the random location is within your process space.

Upvotes: 7

Related Questions