malloc + fork 会导致内存泄漏吗?

3
  1. 父进程使用malloc()函数分配内存。
  2. fork操作。
  3. 父进程修改已分配的内存块。
  4. 写时复制(CoW)机制启动,创建一个修改后的内存块的副本,并保留原始内存块的副本。
  5. 子进程不知道也不关心父进程的内存块,并且不会在其拥有的副本上调用free()函数。
  6. 内存泄漏!

我是正确的吗?还是错了?如果是后者,实际上会发生什么?


1
只有当子进程尝试修改内存块的内容时,才会在子进程中调用CoW。子进程是父进程的精确副本(有一些不继承的东西,请参见“man fork”)。在终止子进程之前,由程序员调用free()是必要的。虽然程序结束时的清理也会做到这一点。 - ott--
1个回答

4
malloc()fork()都不会造成内存泄漏——所以我认为你是错误的。
父进程有其自己分配的块的副本。它可以随心所欲地使用它。子进程也有其自己分配的块的副本。它也可以随心所欲地使用它。如果子进程忽略该块,那么它不是泄漏(至少目前不算)。如果子进程糊里糊涂地践踏指针,或从持有分配内存唯一指针的函数返回而没有首先释放它,则会导致泄漏。但这并不是fork()malloc()的错。
请记住,在fork()之后运行相同的代码,进程之间的主要区别是PID和fork()的返回值。其他几乎所有内容(详见POSIX规范中关于fork()的说明)都是相同的。因此,如果代码泄漏,那么这是程序员引入的错误,不是malloc()fork()的错误。
请注意,如果子进程使用exec*()系列函数之一,则原始进程中的所有分配内存都将被释放。新进程会分配新的内存。同样,如果子进程退出,那么内存将被释放。操作系统不会长期失去对内存的跟踪。

简而言之:如果子进程不关心由父进程分配的块,那么它应该使用free()释放。否则,子进程对该块的副本将在内存中存留直到子进程终止或调用exec为止。正确吗? - Martin Sustrik
是的,那是一种相当准确的概括,尽管它忽略了一个事实,即通过 free() 返回的释放内存通常会留给另一个对 malloc() 的调用以供重用,而不是返回给操作系统。 - Jonathan Leffler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接