And*_*ech 85 c memory-management
假设我有以下C代码:
int main () {
  int *p = malloc(10 * sizeof *p);
  *p = 42;
  return 0;  //Exiting without freeing the allocated memory
}
当我编译并执行该C程序时,即在内存中分配一些空间之后,在我退出应用程序并且进程终止后,我分配的内存是否仍会被分配(即基本上占用空间)?
Yac*_*oby 104
这取决于操作系统.大多数现代(和所有主要)操作系统将释放程序结束时未被程序释放的内存.
依赖于此是不好的做法,最好明确地释放它.问题不仅在于您的代码看起来很糟糕.您可能决定将小程序集成到一个较大的,长期运行的程序中.然后一段时间后,你必须花费数小时追踪内存泄漏.
依赖于操作系统的功能也使代码不那么便携.
Kev*_*eid 43
通常,现代通用操作系统在终止进程后进行清理.这是必要的,因为选择是让系统随着时间的推移失去资源和需要重新启动由于这是写得不好或根本就很少发生的那泄漏资源错误的程序.
无论如何,让您的程序明确地释放其资源可能是出于各种原因的良好实践,例如:
但是,这是跳过释放内存的原因:高效关机.例如,假设您的应用程序在内存中包含一个大缓存.如果它退出时它会通过整个缓存结构并一次释放一个,这没有任何用处,浪费资源.特别是,考虑操作系统将包含缓存的内存页面交换到磁盘的情况; 通过走结构并释放它,你将所有这些页面一次性地带回到内存中,浪费了大量的时间和精力,没有实际的好处,甚至可能导致系统上的其他程序被换掉!
作为一个相关的例子,有一些高性能服务器通过为每个请求创建一个进程来工作,然后在完成时退出它; 通过这种方式,他们甚至不必跟踪内存分配,并且根本不进行任何释放或垃圾收集,因为在进程结束时所有内容都会消失回操作系统的可用内存.(在使用自定义内存分配器的进程中可以完成同样的事情,但需要非常仔细的编程;基本上在OS进程中制定自己的"轻量级进程"概念.)
我很抱歉在最后一篇帖子发布到这个帖子后这么久了.
还有一点.并非所有程序都能让它出色地退出.崩溃和ctrl-C等将导致程序以不受控制的方式退出.如果您的操作系统没有释放堆,清理堆栈,删除静态变量等,最终会导致系统崩溃或内存泄漏.
有趣的是,Ubuntu中的崩溃/中断,我怀疑所有其他现代操作系统,确实存在"处理"资源的问题.当程序结束/崩溃时,套接字,文件,设备等可以保持"打开".在优雅退出之前,作为清理工作的一部分,使用"手柄"或"描述符"关闭任何东西也是一种很好的做法.
我目前正在开发一个大量使用套接字的程序.当我陷入困境时,我必须从中调出ctrl-c,因此,搁置我的插座.我添加了一个std :: vector来收集所有打开的套接字列表和一个捕获sigint和sigterm的sigaction处理程序.处理程序遍历列表并关闭套接字.我计划在抛出前使用类似的清理程序,这将导致提前终止.
有人关心这个设计吗?
这里发生的事情(在现代操作系统中)是你的程序在自己的"进程"中运行.这是一个操作系统实体,具有自己的地址空间,文件描述符等.您的malloc调用是从"堆"分配内存,或分配给您的进程的未分配内存页.
当您的程序结束时,如本示例所示,分配给您的流程的所有资源都只是由操作系统回收/拆除.在内存的情况下,分配给您的所有内存页面都只是标记为"空闲"并循环使用其他进程.页面是一个比malloc处理的更低层次的概念 - 因此,当整个事物被清理时,malloc/free的细节都被简单地冲走了.
这是道德等同的,当你完成使用你的笔记本电脑并想把它交给朋友时,你不必费心去个别删除每个文件.你只需格式化硬盘.
所有这些都说,正如所有其他回答者所指出的那样,依靠这一点并不是一种好的做法: