[英]Does terminating a program reclaim memory in the same way as free()?
我看到了堆栈溢出问题的答案 ,该问题表明在ac程序的最后释放内存实际上是有害的,因为它会将不会再次使用的变量移动到系统内存中。
我很困惑,为什么C中的free()方法会比在程序结束时回收堆的操作系统做任何不同的事情。
有没有人知道在内存管理方面free()和终止之间是否存在真正的区别?如果是这样,操作系统如何区别对待这两者?
例如
这两个短节目会发生什么不同吗?
void main() {
int* mem = malloc(1);
return 0;
}
void main() {
int* mem = malloc(1);
free(mem);
return 0;
}
不,终止程序,如exit
或abort
,不会以与free
相同的方式回收内存。 使用free
会导致某些活动在操作系统丢弃malloc
和free
维护的数据时最终无效。
exit
有一些复杂性,因为它不会立即终止程序。 现在,让我们考虑一下立即终止程序的效果,并考虑以后的并发症。
在通用多用户操作系统中,当进程终止时,操作系统释放其用于其他目的的存储器。 1在很大程度上,这仅仅意味着操作系统会执行一些会计操作。
相反,当您调用free
,程序内部的软件会运行,并且必须查找正在释放的内存大小,然后将有关该内存的信息插入到它正在维护的内存池中。 可能有数千或数万(或更多)此类分配。 释放其所有数据的程序可能必须执行数千次free
调用。 然而,最后,当程序退出时, free
发出的所有更改都将消失,因为操作系统将丢弃有关该内存池的所有数据 - 所有数据都在内存页面中,操作系统无法保留。
所以,在这方面, 你链接的答案是正确的, free
电话是一种浪费。 并且,正如它所指出的那样,必须遍历程序中的所有数据结构以获取它们中的指针,以便它们指向的内存可以被释放,从而导致所有这些数据结构在被换出时被读入内存到磁盘。 对于大型程序,可能需要相当长的时间和其他资源。
另一方面,目前尚不清楚是否容易避免许多free
电话。 这是因为释放内存不是终止程序必须清理的唯一内容。 程序可能希望将最终数据写入文件或将最终消息发送到网络连接。 此外,程序可能没有直接建立所有这些上下文。 大多数大型程序都依赖于软件层,每个软件包都可能已经建立了自己的上下文,并且通常无法告诉其他软件“我想立即退出。 完成有价值的上下文,但跳过所有释放内存。“因此,所有期望的清理任务可能与自由内存任务交织在一起,并且可能没有好的方法来解开它们。
通常应编写软件,以便在程序突然中止时不会发生任何可怕的事情(因为这可能是由于断电而不仅仅是故意的用户操作)。 但即使一个程序可能能够容忍中止,在优雅的退出中仍然有价值。
返回exit
,调用C exit
例程不会立即退出程序。 调用退出处理程序(使用atexit
注册),刷新流缓冲区,关闭流。 您调用的任何软件库可能已经设置了自己的退出处理程序,以便在程序退出时可以完成。 所以,如果你想确保你在程序中使用的库在你结束程序时没有free
调用,你必须调用abort
,而不是exit
。 但通常优先的是优雅地结束程序,而不是通过中止。 调用abort
不会调用退出处理程序,刷新流,关闭流或执行其他exit
代码的exit
代码 - 当程序调用abort
时数据可能会丢失。
1释放内存并不意味着它可立即用于其他目的。 具体结果取决于每页内存。 例如:
这两个短节目会发生什么不同吗?
简单的答案是:它没有区别,在两种情况下都会将内存释放到系统中。 调用free()
并不是绝对必要的,并且会产生无限小的开销,但在尝试跟踪更复杂程序中的内存泄漏时可能会有用。
终止程序是否以与
free
相同的方式回收内存?
不完全是:
malloc()
分配了多少块内存,所有这些都可以高效完成。 free()
使得内存块可供程序进一步使用,以便稍后调用malloc()
或realloc()
。 根据其大小和堆的实现,此释放的块可能会也可能不会返回到OS以供其他程序使用。 还值得注意的是碎片问题,其中小块的释放内存可能无法用于更大的分配,因为它们被分配的块包围。 C堆不执行打包或解碎,它只是合并相邻的空闲块。 在离开程序之前释放所有分配的块可能对于调试目的是有用的,但可能是复杂且耗时的,而在程序终止之后系统不需要重用存储器。 free()
是用户级内存管理功能,取决于您当前使用的malloc
实现。 用户级分配器可能维护内存块的链接列表,malloc / free将采用适当大小的块/将其放回。
exit()
销毁地址空间和所有区域。 这与malloc
ed堆以及用于管理进程地址空间的一些其他区域和内核数据结构有关:
每个地址空间由正在使用的许多页面对齐的内存区域组成。 它们从不重叠并代表一组地址,这些地址包含在保护和目的方面彼此相关的页面。 这些区域由struct vm_area_struct表示,大致类似于BSD中的vm_map_entry结构。 为清楚起见,区域可以表示与malloc()一起使用的进程堆,内存映射文件(如共享库)或使用mmap()分配的匿名内存块。 该区域的页面可能仍然需要分配,活动和驻留或已被分页
参考: https : //www.kernel.org/doc/gorman/html/understand/understand007.html
精心设计的程序在退出时释放内存的原因是检查内存泄漏。 如果在上次重新分配后应用程序级内存分配没有变为零,则表示您的内存未正确管理,并且代码中可能存在内存泄漏。
这两个短节目会发生什么不同吗?
是
我很困惑,为什么C中的free()方法会比在程序结束时回收堆的操作系统做任何不同的事情。
操作系统在页面中分配内存。 堆管理器(例如malloc / free实现)从操作系统分配页面并将页面细分为较小的分配。 调用free()通常会将内存返回堆中。 它们不会将页面返回到操作系统。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.