如果我在程序中使用malloc()动态分配内存,但在程序运行期间没有释放内存,那么动态分配的内存会在程序终止后被释放吗?
操作系统将释放通过malloc分配的内存以供其他系统使用。这比你的问题听起来要复杂得多,因为进程使用的物理内存可能会被写入磁盘(页面换出)。但是在Windows、Unix(Linux、MAC OS X、iOS、Android)中,系统将释放其已提交给进程的资源。
或者,如果它没有被释放,并且我一遍又一遍地执行同一个程序,它会每次分配不同的内存块吗?如果是这样,我该如何释放那块内存?
每次启动程序都会获得新的一组内存。这些内存来自系统,并作为虚拟地址提供。现代操作系统使用地址空间布局随机化(ASLR)作为安全功能,这意味着堆应该在每次启动程序时提供唯一的地址。但是由于其他运行的资源已经被整理好了,所以没有必要释放那块内存。
正如你所注意到的,如果下一次运行无法跟踪已经分配的资源的位置,那么它如何能够释放这些资源呢?此外,请注意,您可以同时运行多个程序,分配的内存可能会重叠 - 每个程序可能会看到相同的地址分配,但这是“虚拟内存”,操作系统独立地设置了每个进程,因此它似乎使用相同的内存,但与每个进程相关联的RAM是独立的。当程序执行时不释放内存,在Windows和Unix以及可能的任何其他合理的操作系统上都“可行”。
不释放内存的好处是,操作系统会保留分配给进程的大型内存块的列表,而malloc库则保留了分配给malloc的小内存块的表。
通过不释放内存,当进程终止时,您将节省处理这些小列表的工作。在某些情况下甚至建议这样做(例如
MSDN:服务控制处理程序建议通过不释放内存来处理SERVICE_CONTROL_SHUTDOWN)。
但是,不释放内存的缺点也很明显。
像valgrind和应用程序验证器这样的程序通过监视分配给进程的内存并报告泄漏来检查程序的正确性。
当您不释放内存时,它们会报告很多噪音,使得难以找到无意中的泄漏。如果您在循环内泄漏内存,这将非常重要,因为这会限制程序可以处理的任务大小。
在我的职业生涯中,我曾几次将进程转换为共享对象/dll。这些是有问题的转换,因为预计由OS进程终止处理的泄漏开始在“main”生命周期之外生存。