【问题标题】:Question about memory leak happening in the child process关于子进程发生内存泄漏的问题
【发布时间】:2011-10-07 22:40:29
【问题描述】:

假设函数 func 有 bug 导致内存泄漏。

pid_t childPid;
int status;
childPid = fork();
if (childPid == -1)
  errExit("fork");
if (childPid == 0) /* Child calls func() and */
  exit(func(arg)); /* uses return value as exit status */

/* Parent waits for child to terminate. It can determine the
   result of func() by inspecting 'status'. */
if (wait(&status) == -1)
  errExit("wait");

问题 1> 如果一个程序发生了内存泄露,那么程序最终退出后,是否还会泄露内存,还是系统会收集该程序分配的所有内存,再没有泄露的内存?

问题 2> 父进程调用wait后,子进程的func导致的内存泄露是怎么回事?

【问题讨论】:

    标签: c linux ubuntu-10.04


    【解决方案1】:

    内存泄漏只是一种资源泄漏。

    分配的内存页面,例如 malloc() 被称为“私有页面”,因为它们只属于一个进程(它们可能是与父或子共享的写时复制,但它们仍然是它自己的页面)。

    但是,还有许多其他泄漏资源的方式。某些类型的共享对象不会自动清理;文件系统中的文件不会被自动清理,您的孩子创建的子进程也不会在退出时自动回收。

    【讨论】:

    • 当当前子进程死亡时,当前子进程产生的任何新子进程都不会被回收,但它们的父进程将从现在已死的子进程切换到init ,然后为它的所有孩子调用wait()。所以在某些时候,当它们调用exit() 时,那些产生的子进程将被正确清理......如果不是由它们的父进程,那么由init。话虽如此,在它们运行时,即使父级是init,它们也会继续消耗资源,所以我同意这是另一种“泄漏”类型。
    【解决方案2】:

    如果一个程序发生内存泄漏,程序最后退出后,会不会 仍然泄漏内存或系统将收集由分配的所有内存 程序并且没有更多的内存泄漏?

    系统会从子进程中收集所有的内存资源,不会再有子进程的内存泄露。此外,对fork() 的调用将父进程和子进程的内存空间分开,因此子进程中的泄漏不会在父进程中泄漏,除非您在两者中调用相同的错误函数。

    父进程调用wait后,泄露的内存是怎么回事 子进程的func引起的?

    在父进程中调用wait(),和子进程泄露内存真的没有任何关系。在父进程中调用wait() 只会导致父进程阻塞等待指示子进程已完成的信号。子进程在完成之前仍然必须先调用func(),因为它必须将func() 的返回值传递给exit()。因此,func() 在技术上仍然可以“泄漏”内存,因为它会在堆上分配一些内存,但不会清理它,即使操作系统的清理操作几乎是在调用 func() 之后立即发生的。换句话说,在对exit() 的调用完成后,操作系统已经释放了孩子使用的资源,但func() 本身仍然无法释放它尝试分配的任何内存。

    【讨论】:

      【解决方案3】:

      任何现代操作系统都不允许子进程(或任何进程)在终止后使系统处于不一致的状态。

      如果函数存在缺陷,导致分段错误,操作系统通常会在攻击后立即使用信号SIGSEGV 终止进程,并且父进程将通过wait 确认子进程有信号退出,不正常。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-27
        • 1970-01-01
        • 2016-07-28
        相关资源
        最近更新 更多