Does terminating a program reclaim memory in the same way as free()?

ngo*_*d97 5 c memory-leaks memory-management

I saw this answer to a stack overflow question that says that freeing memory at the very end of a c program is actually harmful because it moves variables that wouldn't be used again into system memory.

I'm confused why the free() method in C would do anything different than the operating system reclaiming the heap at the end of the program.

Does anyone know if there is a real difference between free() and termination in terms of memory management and if so how the operating system may treat these two differently?

e.g.

would anything different happen between these two short programs?

void main() {
    int* mem = malloc(1);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)
void main() {
    int* mem = malloc(1);
    free(mem);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*hil 6

不可以,与exit或一样,终止程序abort不会以与相同的方式回收内存free。使用free会导致某些活动,当操作系统丢弃由malloc和维护的数据时,这些活动最终将无效free

exit有一些麻烦,因为它不会立即终止程序。现在,让我们考虑立即终止程序的效果,然后再考虑复杂性。

在通用多用户操作系统中,当进程终止时,操作系统将释放其用于其他目的的内存。1在很大程度上,这只是意味着操作系统会执行一些会计操作。

相反,当您调用时free,程序中的软件将运行,并且它必须查找您要释放的内存的大小,然后将有关该内存的信息插入到它正在维护的内存池中。这样的分配可能有成千上万。释放所有数据的程序可能必须执行数千个对的调用free。但是,最后,当程序退出时,由它产生的所有更改free都将消失,因为操作系统将丢弃有关该内存池的所有数据-所有数据都在操作系统不保留的内存页中。

因此,就此而言,您链接到的答案是正确的,打电话free是浪费。而且,正如所指出的那样,必须遍历程序中的所有数据结构以获取它们中的指针,以便它们所指向的内存可以被释放,如果这些数据结构已被换出,则它们将被读入内存中。到磁盘。对于大型程序,可能需要花费大量时间和其他资源。

另一方面,不清楚是否容易避免多次致电free。这是因为释放内存并不是终止程序唯一需要清除的内容。程序可能希望将最终数据写入文件或将最终消息发送到网络连接。此外,程序可能没有直接建立所有这些上下文。大多数大型程序都依赖于软件层,并且每个软件包可能都设置了自己的上下文,并且通常没有提供任何方法告诉其他软件“我现在要退出。完成有价值的上下文,但是跳过所有的内存释放。”因此,所有需要的清理任务可能会与自由内存任务交织在一起,并且可能没有解开它们的好方法。

通常应该编写软件,以便在程序突然中止时不会有任何可怕的事情发生(因为这可能是由于断电而引起的,而不仅仅是故意的用户操作)。但是,即使程序可以忍受中止,但正常退出仍然会有价值。

回到exit,调用C exit例程不会立即退出程序。atexit调用退出处理程序(在处注册),刷新流缓冲区,并关闭流。您调用的所有软件库都可能设置了自己的退出处理程序,以便它们可以在程序退出时完成。因此,如果要确保在程序free结束时没有调用您程序中使用的库,则必须调用abort,而不是exit。但是通常最好以优雅的方式结束程序,而不是中止程序。调用abort将不会调用出口处理程序,刷新流,关闭流或执行其他关闭处理的代码exit-程序调用时数据可能会丢失abort

脚注

1释放内存并不意味着它立即可用于其他目的。具体结果取决于内存的每一页。例如:

  • 如果与其他进程共享内存,则它们仍然需要该内存,因此,释放该进程使用该内存只会减少使用该内存的进程的数量。它不能立即用于任何其他用途。
  • 如果该内存未由任何其他进程使用,但包含从磁盘上的文件映射的数据,则操作系统可能会在需要时将其标记为可用,但暂时不进行处理。这是因为您可能会再次运行同一程序,并且如果数据仍在内存中会很好,那么为什么不把它留在原地以防万一呢?该数据甚至可能由使用相同文件的其他程序使用。(例如,许多程序可能使用相同的共享库。)
  • 如果该内存未被任何其他进程使用,而只是被程序用作工作区,而不是从文件映射而来,则系统可能会将其标记为立即可用并且不包含任何有用的东西。