C - fork在父进程malloc之后.子进程是否需要释放它



回答你脑海中的问题:是的,这是为了上学。不,我不能用线程。是的,我在寻找答案,有些人说"是",有些人说"不是"。我也会核实我的教授的事实,因为我不想在别人给我评分时不公平地失分,因为他们要求"修正"这个错误。"

话虽如此……考虑在Linux系统上用c编写这个简单的程序。我把东西放进去,然后分叉。我把我的项目归结为具体的问题:

#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 directoryn", 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: %in", WEXITSTATUS(status));
        }
    }
    free(something);
    return 0;
}

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

但是我想起来,当使用fork()时,无论malloc是什么,都将包含相同的内存地址,所以父节点和子节点指向相同的东西吗?我是否也需要在子进程中释放资源?只是复制了指针,还是指针所指向的数据也被复制了?

我使用了valgrind,当子进程退出时,它只是抱怨所有的内存仍然是可访问的。它到底是怎么"还能联系到"的?事实是,它是"仍然可达"回答我的问题,说父和子都指向相同的东西和父的唯一负责释放内存?

在没有呼叫exec家族的情况下,您必须free()它。父进程和子进程不指向相同的东西,因为它们是独立的进程,不共享相同的地址空间。想象一下在另一种情况下会发生什么,例如,如果父母free()设置它,然后孩子试图访问它。

如果您调用execvp()之类的东西,那么正如tmyklebu提到的,您的进程就会被擦除,而您不必做任何事情。

"Still reachable"意味着你仍然有一个对它的引用,但是你还没有free() d它。由于在终止时所有的内存都会获得free() d,因此与永久丢失已分配内存的实际内存泄漏相比,这有时并不是什么大问题。Valgrind的FAQ说:"你的程序可能没有问题——它没有释放一些内存。这很常见,也很合理。"对这个问题的看法各不相同——有些人说显式地free()所有东西是一种好形式,另一些人说这样做是毫无意义的资源浪费,因为程序终止本身将为您做所有的事情。

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

_exit退出程序,表示分配的内存已经用完了。

你不需要显式地在子进程中设置free;事实上(因为COW的事情)这样做并不是一个好主意。

execvp之前调用free是没有意义的,它实际上使你的代码更不容易重用/可移植,因为如果调用进程是多线程的,在fork之后的子进程中调用free是无效的。

相关内容

  • 没有找到相关文章

最新更新