【问题标题】:Why I have different output with valgrind using fork()为什么我使用 fork() 与 valgrind 有不同的输出
【发布时间】:2018-05-11 06:58:56
【问题描述】:

我有一个无法解释的问题。

检查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 的新手,我不明白这对我来说是否有问题。为什么会这样?

这是在带有 GCC 7 的 Linux Mint 18.2 上编译的。

【问题讨论】:

  • 为什么你首先期望父母的输出和孩子的输出之间有任何特定的顺序?
  • @AndrewHenle 你的意思是这些流程的控制流程可以不同,我不能转达吗?我的意思是,我知道父进程和子进程有不同的地址空间,但我不确定顺序。
  • 两个不同的进程会有两个不同的线程,因此并行运行。两者之间的一切如何运作变得有些复杂,但是不,您不能依赖它们以特定顺序运行任务。这听起来像是一种竞争条件。
  • @Thebluefish 我读到这些行的顺序是由 CPU 调度程序决定的。所以如果我再次运行这个程序,我可能会得到完全不同的结果,但我不确定,因为如果我只在我的系统上运行可执行文件the order never changes
  • @Michi 乍一看似乎如此,但如果系统非常忙于处理许多其他进程,它确实也可能会发生变化

标签: c fork valgrind linux-mint gcc7


【解决方案1】:

Valgrind“检测”您的代码以检查泄漏。这意味着添加额外的代码、变量等。This 答案对此提供了非常快速的概述。

在一组情况下,您的程序可能“通常”以特定顺序执行。但是,如果您更改这些情况(例如,使用valgrind 进行检测),运行顺序可能会更改。这将取决于许多因素,包括调度程序等。

这是一个非常简单的答案,但本质上,除非您使用自己的调度程序、信号量等来控制代码流,否则如果您大幅更改代码/环境,则感知到的执行顺序可能会发生变化。

【讨论】:

    【解决方案2】:

    Valgrind 在您的代码中添加了一些其他代码来检查内存泄漏。但这不会导致您的程序产生不同的输出。没有 Valgrind 也可能发生这种情况。即使没有 valgrind,也可能有不同的输出。 Fork 将创建另一个进程,从那里您的程序将以任何顺序运行。您的程序不应依赖于执行顺序,您需要保护机制(互斥/信号量)来控制共享资源的访问。

    【讨论】:

      猜你喜欢
      • 2020-10-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-03
      • 1970-01-01
      • 1970-01-01
      • 2020-12-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多