0

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.

Michi
  • 5,175
  • 7
  • 33
  • 58
  • 1
    Why do you expect any particular order between the parent's output and the child's output in the first place? – Andrew Henle Nov 27 '17 at 22:46
  • @AndrewHenle You mean that the control flow of these processes can be different and I cannot relay on that? I mean, I know that the parent and child processes have separate address spaces, but I was not sure about the order. – Michi Nov 27 '17 at 22:54
  • Two different processes will have two different threads and thus run in parallel. How everything works out between the two gets somewhat complex, but no, you cannot rely on them running tasks in a specific order. This sounds like a race condition. –  Nov 27 '17 at 22:57
  • @Thebluefish I was reading that the order of these lines are determined by the CPU scheduler. So if I run this program again, I may get a totally different result, but I was not sure about that, because if I only run the executable [the order never changes](https://pastebin.com/raw/mxP64Nhp) on my System. – Michi Nov 27 '17 at 23:00
  • @Michi It might seem so at first glance, but it indeed might also change then if the system is very busy with many other processes for example – Ctx Nov 27 '17 at 23:13
  • @Ctx Yes, I noticed after [I made some changes to the Code](https://pastebin.com/raw/LMB3qYX6) and I got the [following Output](https://pastebin.com/raw/BSSqvtRr). – Michi Nov 27 '17 at 23:19
  • Please do not post links to your program output, Rather, edit the question, document that it is a 'edit' and why, then the new information. – user3629249 Nov 28 '17 at 09:13
  • the code seems to run differently with valgrind, because valgrind is yet another process running so the output can be in a slightly different order. – user3629249 Nov 28 '17 at 09:14

2 Answers2

2

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.

roelofs
  • 2,132
  • 20
  • 25
1

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.

kadina
  • 5,042
  • 4
  • 42
  • 83