在父级中的malloc之后的fork ...子进程是否需要释放它?

use*_*200 12 c malloc fork dynamic execvp

你头脑中的问题答案:是的,这是针对学校的.不,我不能使用线程.是的,我寻找答案,有些人说"是",其他人则说"不".我也正在检查我的教授,因为如果其他人要对其进行评分并且他们要求"修复",我不想不公平地失去分数.

有了这样说......在Linux系统上考虑这个简单的c程序.我malloc的东西,然后叉.我把我的项目归结为确切的问题:

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

int main( void )
{
    char * args [] = { "someinvalidcommand", NULL };

    // malloc before the fork (happens in parent process)
    char * something = (char *)malloc(sizeof(char));

    pid_t child_pid = fork();

    // are there now two things that need to be freed:
    // one for each process?

    if(child_pid == 0) // child process
    {
        //free(something); // is this needed?

        // execvp (it won't return if succeeded)
        if(execvp(args[0], args) < 0)
        {
            // or do I only need to free it here?
            printf("%s: No such file or directory\n", args[0]);
            /*
             * EDIT: Calling it here seems to fix the issue.  It turns out
             * that the system calls were the ones with the "still reachable"
             * errors, so I guess it's not all that important that the
             * memory be freed.
             *
             * free(something)
             */
            _exit(1);
        }
    }
    else // parent process
    {
        int status;
        while(wait(&status) != child_pid);
        if(status != 0)
        {
            printf("command status: %i\n", WEXITSTATUS(status));
        }
    }

    free(something);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

现在这是令人困惑的地方.据我所知,fork在该特定状态(包括文本,数据等)创建父进程的精确副本.我在某处读到这包括任何malloc'd(所以,堆).但是,我在其他地方读到它并不是因为所谓的"写时复制",但后来在其他地方读到"写时复制"只是一种透明且无关紧要的优化.但是我读到的最有意义的是,因为它是一个COPY,它有它自己的,好的......一切.

但后来我记得当使用fork()时,malloc所包含的内容将包含相同的内存地址,父和子指向相同的内容也是如此?我是否还需要释放孩子的资源?是仅复制指针,还是指针指向的数据也被复制?

我使用了valgrind,当子进程退出时,它只是抱怨所有内存仍然可以访问.究竟是什么"仍然可以到达?" 它"仍然可以访问"的事实是否回答了我的问题,并说父母和孩子指向同一个事物而父母是唯一一个负责释放记忆的人?

Cro*_*man 5

由于没有exec家人的电话,您必须这样free()做。父项和子项不指向同一事物,因为它们是独立的进程,并且不共享相同的地址空间。想象一下free(),例如,如果父母选择了替代方法,然后孩子尝试访问替代方法,将会发生什么情况。

如果确实调用了execvp(),则正如tmyklebu提到的那样,您的过程就被清除了,您无需执行任何操作。

“仍可访问”表示您仍然可以引用它,但free()尚未找到它。由于无论如何您的所有内存都会free()在终止时被删除,因此与实际的内存泄漏相比,这有时不是什么大问题,在实际的内存泄漏中,您永久丢失分配的内存。Valgrind的FAQ本身说:“您的程序可能还不错-它没有释放它可能拥有的一些内存。这很普遍,而且通常很合理。” 关于该主题的观点各不相同-有些人说,显式地free()一切都是好方法,另一些人说,执行程序终止将要为您自己做的事情是浪费资源。

  • @tmyklebu:我就是这么说的。“父母和孩子没有指向同一个事物……想象一下在替代方案下会发生什么。” (2认同)
  • 如果你想释放他们,你就必须释放他们。问题的背景显然是孩子需要释放它们,还是父母会为你释放它们?答案是否定的,父母不会为孩子释放它们,如果你想让孩子释放它们,孩子就必须释放它。 (2认同)

tmy*_*ebu 5

execvp擦除您的地址空间,因此分配的内存消失了。

_exit退出你的程序,意味着分配的内存消失了。

您不需要free在子进程中明确任何内容;事实上(因为牛的事情)这样做并不是一个好主意。