在C或c++应用程序中出现内存泄漏是可以接受的吗?

如果分配一些内存并一直使用到应用程序中的最后一行代码(例如,全局对象的析构函数),会怎样?只要内存消耗不随时间增长,那么当应用程序终止时(在Windows、Mac和Linux上),是否可以信任操作系统为您释放内存?如果内存一直被使用,直到被操作系统释放,您会认为这是真正的内存泄漏吗?

如果是第三方库将这种情况强加给您,该怎么办?会拒绝使用第三方库,不管它有多好?

我只看到了一个实际的缺点,那就是这些良性泄漏将在内存泄漏检测工具中显示为误报。


当前回答

我的回答是没有。

从理论上讲,如果你把东西弄得乱七八糟,操作系统会帮你清理干净(这很粗鲁,但由于计算机没有感情,这可能是可以接受的)。但是,您无法预测程序运行时可能发生的每一种情况。因此(除非您能够对某些行为进行正式的证明),从专业的角度来看,造成内存泄漏是不负责任和草率的。

如果第三方组件泄漏内存,这是一个非常强烈的反对使用它的理由,不仅因为即将发生的影响,而且因为它表明程序员工作草率,这也可能影响其他指标。现在,当考虑遗留系统时,这是困难的(考虑web浏览组件:据我所知,它们都泄漏内存),但这应该是标准。

其他回答

我看到了和所有场景问题一样的问题,比如:当程序改变时,会发生什么?突然,这个小内存泄漏被调用了1000万次,而程序的结尾在不同的地方,所以它很重要?如果它在库中,那么请向库维护者记录错误,不要在您自己的代码中泄漏。

在这类问题中,语境就是一切。就我个人而言,我不能忍受漏洞,在我的代码中,如果它们突然出现,我就会竭尽全力去修复它们,但修复漏洞并不总是值得的,当人们按小时支付我的报酬时,我有时会告诉他们,我的费用不值得我修复他们代码中的漏洞。让我给你们举个例子:

I was triaging a project, doing some perf work and fixing a lot of bugs. There was a leak during the applications initialization that I tracked down, and fully understood. Fixing it properly would have required a day or so refactoring a piece of otherwise functional code. I could have done something hacky (like stuffing the value into a global and grabbing it some point I know it was no longer in use to free), but that would have just caused more confusion to the next guy who had to touch the code.

就我个人而言,我一开始就不会以这种方式编写代码,但我们大多数人并不总是在设计良好的原始代码库上工作,有时你必须务实地看待这些事情。修复150字节泄漏所花费的时间可以用来改进算法,从而减少兆字节的内存。

最终,我决定为一个使用大约1g内存并运行在专用机器上的应用程序泄露150个字节不值得修复,所以我写了一条评论说它被泄露了,为了修复它需要改变什么,以及为什么当时不值得。

除非“使用”的内存量不断增长,否则我不认为这是内存泄漏。有一些未释放的内存,虽然不是理想的,但不是一个大问题,除非所需的内存数量不断增长。

从历史上看,在某些边缘情况下,它在某些操作系统上确实很重要。这些边缘情况在未来可能会存在。

Here's an example, on SunOS in the Sun 3 era, there was an issue if a process used exec (or more traditionally fork and then exec), the subsequent new process would inherit the same memory footprint as the parent and it could not be shrunk. If a parent process allocated 1/2 gig of memory and didn't free it before calling exec, the child process would start using that same 1/2 gig (even though it wasn't allocated). This behavior was best exhibited by SunTools (their default windowing system), which was a memory hog. Every app that it spawned was created via fork/exec and inherited SunTools footprint, quickly filling up swap space.

如果你在程序开始时分配了一堆内存,但退出时没有释放它,这本身并不是内存泄漏。内存泄漏是指当程序循环遍历一段代码时,该代码分配堆,然后在没有释放它的情况下“失去跟踪”。

事实上,在退出之前不需要调用free()或delete。当进程退出时,它的所有内存都被操作系统回收(POSIX当然就是这种情况。在其他操作系统上-特别是嵌入式的- YMMV)。

对于退出时不释放内存,我唯一要注意的是,如果你重构了你的程序,例如,它变成了一个等待输入的服务,做你的程序所做的任何事情,然后循环等待另一个服务调用,那么你所编写的代码可能会变成内存泄漏。