当你退出一个C应用程序时,malloc-ed的内存是否自动释放?

假设我有以下C代码:

int main () { int *p = malloc(10 * sizeof *p); *p = 42; return 0; //Exiting without freeing the allocated memory } 

当我编译并执行这个C程序,即在分配内存空间之后,我分配的内存在我退出应用程序之后还会被分配(即基本占用空间),并且进程终止?

这取决于操作系统。 大多数现代(以及所有主stream)操作系统将在程序结束时释放不被程序释放的内存。

依靠这个是不好的做法,最好明确地解放它。 问题不只是你的代码看起来不好。 你可能会决定你想把你的小程序整合到一个更大,更长的程序中。 然后一段时间后,你必须花费数小时来追踪内存泄漏。
依靠操作系统的一个特性也使得代码更加便于移植。

一般来说, 现代通用操作系统在终止进程之后会清理干净 。 这是必要的,因为替代scheme是系统随着时间的过去而丢失资源,并且由于程序写得不好或者只是具有很less发生资源泄漏的错误而需要重启。

无论如何,让程序明确地释放资源可能是一个很好的做法,出于各种原因,比如:

  • 如果有额外的资源在操作系统退出时没有被清除,比如临时文件或者对外部资源状态的任何改变 ,那么你将需要代码来处理退出时的所有这些事情,而这个往往优雅地结合释放记忆。
  • 如果你的程序开始有一个更长的生命周期,那么你不会想要释放内存的唯一方法是退出。 例如,您可能希望将程序转换为服务器(守护进程),该服务器在处理针对各个工作单元的许多请求时一直运行,或者您的程序可能成为较大程序的一小部分。

但是,这是跳过内存释放的一个原因:高效的closures 。 例如,假设你的应用程序在内存中包含一个大的caching。 如果它退出,它会遍历整个caching结构,并一次释放一块,没有任何用处,浪费资源。 尤其是考虑到操作系统将包含caching的内存页面交换到磁盘的情况; 通过走结构和释放它,你会把所有这些页面一次性带回到内存中 ,浪费大量的时间和精力而没有实际的好处,甚至可能导致系统上的其他程序被换掉!

作为一个相关的例子,有高性能的服务器通过为每个请求创build一个进程来工作,然后在完成时退出; 通过这种方式,他们甚至不需要跟踪内存分配情况 ,也绝不会进行任何释放或垃圾回收,因为在进程结束时,所有内容都会消失在操作系统的空闲内存中。 (在一个使用自定义内存分配器的进程中可以完成同样的事情,但是需要非常小心的编程;本质上是在操作系统进程中使用自己的“轻量级进程”概念。

我很抱歉张贴在这个post的最后一篇文章很长时间。

还有一点。 并不是所有的程序都能够优雅地退出。 崩溃和ctrl-C等将导致程序以不受控制的方式退出。 如果你的操作系统没有释放你的堆,清理你的堆栈,删除静态variables等,最终会导致系统内存泄漏或者更糟。

除此之外,有趣的是,在Ubuntu中崩溃/中断,我怀疑所有其他现代操作系统,确实有“处理”资源的问题,当程序结束/崩溃时,套接字,文件,设备等可以保持“打开”。也是一个很好的习惯,在优雅退出之前用“处理”或“描述符”作为清理的一部分closures任何东西。

我目前正在开发一个使用套接字的程序。 当我被困在一个悬挂,我不得不ctrl-C出来,因此,搁浅我的sockets。 我添加了一个std :: vector来收集所有打开的套接字的列表以及一个可以捕获sigint和sigterm的sigaction处理程序。 处理程序遍历列表并closures套接字。 我打算在投掷之前做一个类似的清理程序,这会导致提前终止。

任何人都在意这个devise的评论?

这里发生的事情( 在现代操作系统中 )是,你的程序在自己的“过程”中运行。 这是一个拥有自己的地址空间,文件描述符等的操作系统实体。你的malloc调用是从“堆”分配内存,或者是分配给你的进程的未分配的内存页面。

当你的程序结束时,就像在这个例子中一样,分配给你的进程的所有资源都被操作系统简单地回收/拆除。 在内存的情况下,分配给您的所有内存页面都被简单地标记为“空闲”,并被回收用于其他进程。 页面是一个比malloc句柄低一级的概念 – 因此,malloc / free的细节在整个事情得到清理时都被简单地冲走。

当你使用笔记本电脑并想把它交给朋友的时候,这就是道德上的等同物,你不必费尽心思地单独删除每个文件。 您只需格式化硬盘。

所有这一切,正如所有其他答复者所指出的那样,依靠这一点并不是好的做法:

  1. 你应该总是编程来处理资源,而在C中这也意味着内存。 您最终可能会将代码embedded到库中,或者最终运行的时间可能会超出您的预期。
  2. 有些操作系统(比较老的,也可能是一些现代的embedded式操作系统)可能不能保持这样严格的进程边界,你的分配可能会影响到其他地址空间。

是。 操作系统清理资源。 那么…旧版本的NetWare没有。

编辑:正如圣哈辛托指出的那样,除了NetWare之外肯定有系统不这样做。 即使在抛弃式的程序中,我也试图养成为了保持习惯而释放所有资源的习惯。

是的,操作系统在过程结束时释放所有内存。

这取决于,操作系统通常会为您清理它,但是如果您正在处理embedded式软件,那么它可能不会被释放。

只要确保你释放它,它可以节省你很多时间,当你可能想要将它集成到一个大型的项目。

这真的取决于操作系统,但是对于所有遇到的操作系统,内存分配将在进程退出时消失。

我认为直接释放是最好的。 未定义的行为是最糟糕的事情,所以如果你在访问过程中仍然有访问权限,那就去做吧,人们给了它很多很好的理由。

至于在哪里,或者是否,我发现在W98中,真正的问题是'什么时候'(我没有看到一个post强调这一点)。 一个小的模板程序(用于MIDI SysExinput,使用各种malloc'd空格)将释放WndProc的WM_DESTROY位中的内存,但是当我将它移植到一个更大的程序时,它会在退出时崩溃。 我认为这意味着我试图释放操作系统在更大的清理过程中已经释放的东西。 如果我做了WM_CLOSE,然后调用DestroyWindow(),它一切正常,即时清理退出。

虽然这与MIDI缓冲区不完全一样,但最好保持整个过程完整,清理完全,然后退出。 用适度的内存块,这是非常快的。 我发现许多小缓冲区在运行和清理过程中的运行速度比较less的大缓冲区运行得更快

例外可能存在,正如有人所说,当避免从磁盘上的交换文件中拖出大量内存块,但即使这样做可以通过保留更多和更小的分配空间来最小化。