Why I have different output with valgrind using fork()

1.3k views Asked by At

I have a issue which I can not explain it.

Checking with valgrind for memory leaks I noticed that the order in which the program prints is different from the order which I get if I just run the executable of my program.

I reduced my program so that compiles to show where the issue is.

When I compile and run the following code:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main(void)
{
    printf("I am %d\n", (int)getpid() );

    pid_t pid = fork();
    printf("Fork returned %d\n", (int)pid );

    if ( pid < 0 ){
        perror("Fork Faild\n");
        exit(1);
    }
    if ( pid == 0 ){
        printf("I am the child with pid %d\n", (int)getpid());
        sleep(5);
        printf("Child exiting...\n");
        exit(0);
    }

    printf("I am the parent waiting for child to end\n");
    wait(NULL);
    printf("Parent ending.\n");

    return 0;
}

I get the following Output:

michi@michael ~ $ ./program 
I am 18320
Fork returned 18321
I am the parent waiting for child to end
Fork returned 0
I am the child with pid 18321
Child exiting...
Parent ending.

But when I check it with valgrind, I get the Output in another order:

michi@michael ~ $ valgrind --leak-check=full --track-origins=yes ./program
==18361== Memcheck, a memory error detector
==18361== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==18361== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==18361== Command: ./program
==18361== 
I am 18361
Fork returned 18362
Fork returned 0
I am the child with pid 18362
I am the parent waiting for child to end
Child exiting...
==18362== 
==18362== HEAP SUMMARY:
==18362==     in use at exit: 0 bytes in 0 blocks
==18362==   total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==18362== 
==18362== All heap blocks were freed -- no leaks are possible
==18362== 
==18362== For counts of detected and suppressed errors, rerun with: -v
==18362== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Parent ending.
==18361== 
==18361== HEAP SUMMARY:
==18361==     in use at exit: 0 bytes in 0 blocks
==18361==   total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==18361== 
==18361== All heap blocks were freed -- no leaks are possible
==18361== 
==18361== For counts of detected and suppressed errors, rerun with: -v
==18361== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

I am new with fork and I can not understand if this is a problem to me or not. Why this happens?

This was compiled on Linux Mint 18.2 with GCC 7.

2

There are 2 answers

0
roelofs On

Valgrind 'instruments' your code in order to check for leaks. This means adding additional code, variables, etc. This answer gives a very quick overview on this.

Under one set of circumstances, your program may 'usually' execute in a particular order. However, if you change those circumstances (by, say, instrumenting with valgrind), the running order may change. It will depend on a number of factors, including schedulers, etc.

This is a very simplified answer, but essentially, unless you control your codeflow with your own scheduler, semaphores, etc, if you change the code/environment substantially, the perceived execution order can change.

0
kadina On

Valgrind adds some other code into your code to check for the memory leaks. But this is not cause for your program for different output. It can happen with out Valgrind also. Even without valgrind, there may be chance for different output. Fork will create another process, from there on your program will run in any order. Your program shouldn't depend on the order of execution and you need protection mechanism (mutex / semaphore) to control the access of shared resources.