exec()更改程序映像后malloc的内存会发生什么?

Jon*_*erg 28 c c++ memory-management exec

我知道当我exec()在Linux中调用其中一个系统调用时,它将使用新映像替换当前正在运行的进程.因此,当我分叉一个新进程并运行时exec(),子进程将被替换为新进程.

我从堆中分配的内存会发生什么变化?假设我想解析任意数量的命令并将其发送到exec().为了保持这个任意数字,我可能不得不在某个时刻分配内存,因为我认为我不能正确使用静态大小的数组,所以我可能会使用malloc()或等效的东西.

我需要保持这个内存分配,直到我打电话exec(),但exec()永远不会返回.

内存是否被操作系统回收?

Pet*_*nen 25

调用时fork(),会创建调用进程的副本.这个子进程(几乎)与父进程完全相同,即malloc()保留了分配的内存,您可以自由地阅读或修改它.但是,父进程不会看到修改,因为父进程和子进程完全是分开的.

当您调用exec()子进程时,子进程将被新进程替换.来自execve(2):

execve() does not return on success, and the text, data, bss, and stack
of the calling process are overwritten by that of the program loaded.
Run Code Online (Sandbox Code Playgroud)

通过覆盖该data段,该exec()调用有效地回收了之前分配的内存malloc().

父进程不受所有这些影响.假设您在调用之前在父进程中分配了内存,则内存在父进程fork()中仍然可用.

编辑:malloc()使用匿名内存映射的现代实现,请参阅mmap(2).根据execve(2),内存映射不会通过exec()调用保留,因此也会回收此内存.

  • 这并不能解释堆会发生什么。好的,数据段被覆盖,但这意味着堆被破坏,而不是重置。 (2认同)
  • 堆是数据段。在一个简单的实现中,“malloc()”将使用“brk()”来增长数据段并获得更多内存。当数据段被覆盖时,其大小也会被重置,并且内存被有效地释放。 (2认同)

Jam*_*nze 5

整个堆——分配的内存,以及 malloc 用来管理它的所有逻辑——是被替换的进程映像的一部分。就您的过程而言,它只是消失了。当然,系统会恢复它并回收它。