释放未更改的“写时复制”内存

2023-11-21

我明白了写时复制背后的想法。当我分叉时,堆被标记为 CoW,当任何进程尝试更改它时,都会创建一个副本。问题是:我是否仍然必须在孩子的进程中释放它?假设父级有一个动态 char *array,然后它会分叉。子进程打印一些 const char,然后退出。子进程根本没有改变堆。会不会出现内存泄漏?

编辑:我的子进程在堆上打印数组,但不修改它。 Valgrind 说如果我不释放该数组,就会出现泄漏。当我释放它时没有泄漏/内存错误。


CoW只是一种惰性优化。你可以自由地认为fork()总是毫无延迟地复制进程的完整副本(至少在内存方面)。但…

如果您确实准备了动态数据块以“传递”给 fork 的子进程,那么在 fork 之后,您将拥有两个带有两个动态数据块的进程:父进程和子进程(两者都是副本)。当子进程退出时,它的内存副本将被回收,但父进程应该在 fork 后立即释放该块。

为了更清楚,这里有一个例子:

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 在 fork-exec 技术中也是非常有用的优化,其中子进程什么也不做,只是exec与准备好的论据。exec用指定的可执行映像替换当前进程,保留打开的描述符和其他内容(更多内容请参阅man 2 execve)。这种 fork 之后复制的唯一页面只是当前堆栈帧,这使得 fork-exec 非常有效。

有些系统还提供vfork,这是非常严格的不公平版本的 fork,但在没有 CoW 的系统上,这是有效 vfork-exec 的唯一方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

释放未更改的“写时复制”内存 的相关文章

随机推荐