简体   繁体   English

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

[英]fork after malloc in parent… does the child process need to free it?

Answers to questions in your head: Yes, this is for school. 你头脑中的问题答案:是的,这是针对学校的。 No, I can't use threads for this. 不,我不能使用线程。 And yes, I looked for an answer and some people said "yes" and others said "no." 是的,我寻找答案,有些人说“是”,其他人则说“不”。 I'm also fact-checking my professor because I don't want to unfairly lose points if someone else were to grade it and they require this to be "fixed." 我也正在检查我的教授,因为如果其他人要对其进行评分并且他们要求“修复”,我不想不公平地失去分数。

With that being said... consider this simple program for c on the Linux system. 有了这样说......在Linux系统上考虑这个简单的c程序。 I malloc something and then fork. 我malloc的东西,然后叉。 I boiled down my project to the exact problem: 我把我的项目归结为确切的问题:

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

Now this is where it's slightly confusing. 现在这是令人困惑的地方。 To my knowledge, fork creates an exact copy of the parent process at that particular state (including text, data, etc.). 据我所知,fork在该特定状态(包括文本,数据等)创建父进程的精确副本。 I read somewhere that this includes anything malloc'd (so, the heap). 我在某处读到这包括任何malloc'd(所以,堆)。 However, I read somewhere else that it doesn't because of something called "copy-on-write," but then I read somewhere else that "copy-on-write" is simply an optimization that's transparent and irrelevant. 但是,我在其他地方读到它并不是因为所谓的“写时复制”,但后来在其他地方读到“写时复制”只是一种透明且无关紧要的优化。 But then what I read that made the most sense was that since it's a COPY, it has its own, well... everything. 但是我读到的最有意义的是,因为它是一个COPY,它有它自己的,好的......一切。

But then I recall that when fork() is used, whatever was malloc'd will contain the same memory address, so are the parent and child pointing to the same thing? 但后来我记得当使用fork()时,malloc所包含的内容将包含相同的内存地址,父和子指向相同的内容也是如此? Do I need to free resources in the child, as well? 我是否还需要释放孩子的资源? Are only the pointers copied, or are the data that the pointers are pointing to also copied? 是仅复制指针,还是指针指向的数据也被复制?

I used valgrind and when the child process exits, it simply complains that all the memory is still reachable. 我使用了valgrind,当子进程退出时,它只是抱怨所有内存仍然可以访问。 How exactly is it "still reachable?" 究竟是什么“仍然可以到达?” Does the fact that it's "still reachable" answer my question and say that the parent and child are pointing to the same thing and the parent's the only one responsible for freeing the memory? 它“仍然可以访问”的事实是否回答了我的问题,并说父母和孩子指向同一个事物而父母是唯一一个负责释放记忆的人?

In the absence of the calls to the exec family, you have to free() it. 如果没有对exec系列的调用,你必须free()它。 Parent and child do not point to the same thing, because they are separate processes and do not share the same address space. 父和子不指向同一个东西,因为它们是独立的进程,并且不共享相同的地址空间。 Imagine what would happen under the alternative if the parent free() d it, for instance, and then the child tried to access it. 想象一下,如果父对象free()例如,然后孩子试图访问它free() ,会在替代方案下发生什么。

If you do call something like execvp() , then as tmyklebu mentions, your process just gets wiped, and you don't have to do anything. 如果你确实调用了类似execvp()东西,那么就像tmyklebu所提到的那样,你的过程就会被擦除,你不需要做任何事情。

"Still reachable" means you still have a reference to it, but you haven't free() d it yet. “仍然可以访问”意味着你仍然可以参考它,但你还没有free() Since all your memory gets free() d on termination anyway, this sometimes isn't so much of a problem, compared to getting an actual memory leak where you permanently lose track of allocated memory. 因为无论如何你的所有内存都会在终止时获得free() d,这有点不是一个问题,相比之下,实际的内存泄漏会永久地失去对已分配内存的跟踪。 Valgrind's FAQ itself says that "your program is probably ok -- it didn't free some memory it could have. This is quite common and often reasonable." Valgrind的常见问题解答本身说“你的程序可能没问题 - 它没有释放它可能拥有的内存。这是非常常见且通常是合理的。” Opinions on the subject differ - some folks say it's good form to explicitly free() everything, others say it's a pointless waste of resources to do what program termination is going to do for you all by itself. 关于这个问题的意见有所不同 - 有些人说这是明确地释放()所有内容的好形式,其他人说这是一种毫无意义的资源浪费,无法完成程序终止为你自己做的事情。

execvp wipes your address space, so the allocated memory is gone. execvp擦除你的地址空间,所以分配的内存消失了。

_exit exits your program, meaning the allocated memory is gone. _exit退出程序,意味着分配的内存消失了。

You do not need to explicitly free anything in the child process; 您不需要在子进程中明确free任何内容; in fact (because of the COW thing) it's not a bright idea to do so. 事实上(因为COW的事情)这样做并不是一个好主意。

呼唤free之前execvp是没有意义的,它实际上使你的代码可重用少/便携,因为它不是有效的呼叫free后的孩子fork如果调用进程是多线程的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM