Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

freeing "copy-on-write" memory that wasn't changed

I get the idea behind copy-on-write. When I fork, the heap is marked as CoW, and when any process tries to change it, a copy is made. The question is: do I have to free it in a child's process nonetheless? Suppose a parent has a dynamic char *array, then it forks. A child process prints some const char, and exits. The child process did not alter the heap at all. Will there be a memory leak?

edit: My child process prints the array on heap, but doesn't modify it. Valgrind says there is a leak if I do not free that array. No leak/memory errors when I free it.

like image 843
Krzysiek Avatar asked Feb 24 '14 18:02

Krzysiek


People also ask

Does copy-on-write save memory?

Copy-on-write finds its main use in sharing the virtual memory of operating system processes, in the implementation of the fork system call. Typically, the process does not modify any memory and immediately executes a new process, replacing the address space entirely.

How does copy-on-write work?

A file system feature that makes modifications to separate copies of data when updating is required. Data being read are shared by pointers to one master set. However, when changes are made by one of the applications or users, a copy of the data is made, and the copy is updated.


1 Answers

CoW is just a lazy optimization. You may freely think that fork() always makes the full copy of the process (in terms of memory at least) without any delay. But…

If you did prepare dynamic data chunk to "pass" to fork's child, then after fork you have two processes with two dynamic data chunks: parent and child (both are copies). When child exits, it's copy of memory is reclaimed, but parent should free that chunk right after fork by itself.

To be more clear, here is an example:

char *buf = malloc(123456);
// … fill buf for child …

int res = fork();

if (res == -1) {
    fprintf(stderr, "fork failed\n");
    exit(EXIT_FAILURE);
}

if (res == 0) {
    // this is child process
    // … do work with buf …
    _Exit(EXIT_SUCCESS); // child reclaims buf by means of exit
}

// this is parent process
free(buf); // we don't need it in parent

// … other parent tasks here …

CoW is also very useful optimization in fork-exec technique, where child does nothing but exec with prepared arguments. exec replaces current process with specified executable image, retaining open descriptors and other things (more in man 2 execve). The only page that is copied after such fork is only current stack frame, making fork-exec very effective.

Some systems also provide vfork, that is very restrictive unfair version of fork, but on systems without CoW that is the only way to vfork-exec efficiently.

like image 151
user3125367 Avatar answered Sep 22 '22 03:09

user3125367