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

14

我曾经认为它肯定会,但是……我找不到明确说明。

man 3 exitman 2 _exit 详细说明了进程终止的影响,但没有提到内存泄漏。

Posix 更接近答案:它提到了这个:

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

  • [TYM] [Option Start] 将取消映射在调用进程中映射的任何类型内存块,就像隐式调用 munmap() 来取消映射它们一样。[Option End]

将此与 man 3 malloc 混合使用:

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

因此,我们可以得出结论:如果malloc调用了mmap,那么进程终止可能会调用相应的munmap,但是...(a)这个POSIX规范中的“可选功能”标记有点令人担忧,(b)这是mmap,但sbrk呢?(c)Linux并不完全符合POSIX标准,因此我不确定是否强制混合使用Linux文档和POSIX规范。
我提问的原因是...当库调用失败时,我是否可以直接退出?
if(somecall() == -1) {
    error(EXIT_FAILURE, errno, "Big fat nasty error.\n");
}

或者我需要向上遍历整个堆栈,确保一直到main()的所有内容都被free(),并且只在main()中调用exiterror吗?
前者要简单得多。但是为了感觉容易处理前者,我想在文档中找到明确提到这不是错误,并且这样做是安全的。正如我所说,文档关注明确提到许多将被清理的保证,但未提及此特定保证使我不安。(难道这不是最常见和最明显的情况吗?这不应该首先提到吗?)

2
@KarimManaouil 我怎么会这么想呢?看,我不知道Linux在底层是如何工作的。我只是一个新手,规定自己永远不做任何未经明确允许的事情。我认为,当我处理C++、C、系统调用等时,这种方法是有意义的,因为环境中到处都是最不直观的各种未定义行为。"哦,这肯定能工作,我无法想象它不能工作"的方法已经让我吃过亏了,所以我更喜欢从现在开始保持安全。 - user4385532
2
在这方面,我完全同意你的看法。 - Karim Manaouil
当你询问这样的问题时,即关于每个人都期望以特定方式工作的事物是否确实由相关标准保证以此方式工作,有助于将问题标记为“语言律师”。 - zwol
@zwol 我已经这样做了!但这是第五个标签。然后我想将其标记为“malloc”,但我必须删除其中一个现有的标签才能这样做。“language-lawyer”是我的选择。我仍然希望包括“language-lawyer”,但我不确定要放弃哪个现有的标签。 - user4385532
我认为如果你去掉“c”和“linux”,并改为加上“posix”和“language-lawyer”,这个问题将会引起更多正确人士的关注。它并不是一个C语言问题,也不是特定于Linux的。 - zwol
显示剩余10条评论
2个回答

7

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

在Linux上,内核会回收进程退出时(包括sbrk和mmap)的内存,这是有保证的。请参见mm的源代码

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

可以。这样做没问题。

但是,请注意可能需要考虑其他方面,例如未清理的临时文件、打开的数据库/网络连接等等。例如,如果您的程序保留了一个数据库连接并退出,则服务器端可能不知道何时关闭该连接。

您可以阅读更多有关虚拟内存管理器的信息(它基于旧内核,但该思想仍然适用)。


7
我相信POSIX委员会的意图是所有由malloc分配的内存都应该在你链接到的_exit规范的“进程终止的结果”中被释放。我还可以告诉您,实际上我使用过的每个Unix实现都做到了这一点。
然而,我认为您发现了规范中的一个真正的空缺。POSIX没有关于sbrk分配的内存的说明,因为它根本没有指定sbrk。它对malloc的规范基本上是从C标准中直接引用的,并且C标准故意没有说所有由malloc分配的内存都应该在“正常终止”时被释放,因为存在不这样做的嵌入式环境。正如您指出的,“在进程中创建的内存映射”可能只适用于直接由mmapshmat等分配所做的分配。值得向奥斯汀小组提出解释请求。

C语言的重点很重要:标准有时是故意宽松的,所以这可能会朝任何一边发展。 - alexis
@alexis 是的。C语言在这里是有意放宽限制的。我认为POSIX标准并不打算这样做。 - zwol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接