Почему у меня другой вывод с valgrind с помощью fork ()

У меня проблема, и я не могу ее объяснить.

Проверяя valgrind на наличие утечек памяти, я заметил, что порядок, в котором программа печатает, отличается от порядка, который я получаю, если я просто запускаю исполняемый файл моей программы.

Я сократил свою программу так, чтобы она компилировалась, чтобы показать, в чем проблема.

Когда я компилирую и запускаю следующий код:

#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;
}

Я получаю следующий результат:

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.

Но когда я проверяю это с помощью valgrind, я получаю результат в другом порядке:

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)

Я новичок в использовании fork, и я не могу понять, проблема для меня в этом или нет. Почему так происходит?

Это было скомпилировано на Linux Mint 18.2 с GCC 7.


person Michi    schedule 27.11.2017    source источник
comment
Почему вы вообще ожидаете определенного порядка между выводом родительского и дочернего вывода?   -  person Andrew Henle    schedule 28.11.2017
comment
@AndrewHenle Вы имеете в виду, что поток управления этими процессами может быть разным, и я не могу полагаться на это? Я имею в виду, я знаю, что родительский и дочерний процессы имеют отдельные адресные пространства, но я не был уверен в порядке.   -  person Michi    schedule 28.11.2017
comment
Два разных процесса будут иметь два разных потока и, следовательно, работать параллельно. То, как все работает между ними, становится несколько сложным, но нет, вы не можете полагаться на то, что они запускают задачи в определенном порядке. Это похоже на состояние гонки.   -  person    schedule 28.11.2017
comment
@Thebluefish Я читал, что порядок этих строк определяется планировщиком ЦП. Поэтому, если я снова запущу эту программу, я могу получить совершенно другой результат, но я не был в этом уверен, потому что если я запустил только исполняемый файл порядок никогда не меняется в моей Системе.   -  person Michi    schedule 28.11.2017
comment
@Michi Это может показаться так на первый взгляд, но это действительно может измениться тогда, если система очень занята многими другими процессами, например   -  person Ctx    schedule 28.11.2017
comment
@Ctx Да, я заметил, что после я внес некоторые изменения в код и получил следующий результат.   -  person Michi    schedule 28.11.2017
comment
Пожалуйста, не размещайте ссылки на выходные данные вашей программы. Скорее отредактируйте вопрос, задокументируйте, что это «редактирование» и почему, а затем новую информацию.   -  person user3629249    schedule 28.11.2017
comment
код с valgrind, похоже, работает иначе, потому что valgrind - это еще один запущенный процесс, поэтому выходные данные могут быть в несколько другом порядке.   -  person user3629249    schedule 28.11.2017


Ответы (2)


Valgrind добавляет в ваш код другой код для проверки утечек памяти. Но это не повод для вашей программы для другого вывода. Это может случиться и без Valgrind. Даже без valgrind возможен другой результат. Fork создаст другой процесс, оттуда ваша программа будет запускаться в любом порядке. Ваша программа не должна зависеть от порядка выполнения, и вам нужен механизм защиты (мьютекс / семафор) для управления доступом к разделяемым ресурсам.

person kadina    schedule 27.11.2017

Valgrind 'проверяет' ваш код на предмет утечек. Это означает добавление дополнительного кода, переменных и т. Д. Этот ответ дает очень краткий обзор этого.

При определенных обстоятельствах ваша программа может «обычно» выполняться в определенном порядке. Однако, если вы измените эти обстоятельства (например, с помощью инструмента valgrind), порядок выполнения может измениться. Это будет зависеть от ряда факторов, включая планировщики и т. Д.

Это очень упрощенный ответ, но по сути, если вы не управляете своим потоком кода с помощью собственного планировщика, семафоров и т. Д., Если вы существенно измените код / ​​среду, воспринимаемый порядок выполнения может измениться.

person roelofs    schedule 27.11.2017