Linux是否保证在程序退出时释放malloc已释放的内存?

时间:2018-11-22 16:29:51

标签: memory-leaks malloc posix language-lawyer terminate

我曾经相信它确实可以,但是...我找不到它明确声明的内容。

man 3 exitman 2 _exit详细指定了进程终止的效果,但没有提及内存泄漏。

Posix更近了:它提到了这一点:

  
      
  • 在销毁进程之前,应先取消在进程中创建的内存映射。

  •   
  • [TYM] [Option Start]在调用过程中映射的任何类型的内存块都应被取消映射,就好像隐式调用munmap()来取消映射一样。 [选项结束]

  •   

将此与man 3 malloc混合:

  

通常,malloc()使用sbrk(2)从堆中分配内存,并根据需要调整堆的大小。当分配大于MMAP_THRESHOLD个字节的内存块时,glibc malloc()实现使用mmap(2)将内存分配为私有匿名映射。

因此我们可以得出结论,如果malloc调用了mmap,则进程终止可能会对munmap进行相应的调用,但是...(a)此“可选功能”标签POSIX规范令人担忧,(b)这是mmap,但是sbrk呢? (c)Linux并非100%符合POSIX,因此我不确定是否要求将Linux docu与Posix规范混合使用

我问的原因是...当图书馆呼叫失败时,我可以退出吗?

if(somecall() == -1) {
    error(EXIT_FAILURE, errno, "Big fat nasty error.\n");
}

还是我必须向上堆栈以确保直到main()的所有内容都是free(),并且仅在{{中调用exiterror 1}}?

前者要简单得多。但是,为了轻松使用前者,我想在明确提到的文档中找到它,这不是错误,并且这样做很安全。就像我说的那样,文档确实要明确提及一些肯定会被清除的保证,但事实却没有提及这一具体保证,这令我感到不安。 (这不是最常见,最明显的情况吗?不是一开始就不会提到吗?)

2 个答案:

答案 0 :(得分:7)

此“释放”是在内核级别完成的。因此,您不可能在POSIX API或C规范中找到任何直接内容,因为虚拟内存位于它们的下面。因此,您几乎找不到任何相关的信息-更不用说保证

在Linux上,内核会在进程退出时(sbrk和mmap)回收内存,这是有保证的。参见source code of mm

  

库调用失败时,我可以退出吗?

是的。很好。

但是,请注意,您可能还需要考虑其他注意事项,例如未清理的临时文件,打开的数据库/网络连接等。例如,如果程序使数据库连接保持打开状态并退出,则服务器端可能不知道何时关闭连接。

您可以阅读有关Virtual Memory Manager的更多信息(它基于较早的内核,但该思想仍然适用)。

答案 1 :(得分:7)

我确信POSIX委员会打算将malloc分配的所有内存都作为与您链接的_exit的规范中列出的“进程终止的后果”之一进行重新分配。我还可以告诉您,实际上,我使用过的Unix的每个实现都可以做到这一点。

但是,我认为您在规格中找到了真正的缺陷。 POSIX没有说任何关于sbrk分配的内存的信息,因为它根本没有指定sbrk。它对malloc的规范是逐字逐句地从C标准中获取的,C标准故意并非malloc分配的所有内存都应该被释放。在“正常终止”状态下,因为存在嵌入式嵌入式环境无法执行此操作。而且,正如您所指出的,“在此过程中创建的内存映射”可以理解为仅适用于由mmapshmat等直接进行的分配。向奥斯汀集团提出口译请求可能是值得的。