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

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

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

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


当前回答

我同意vfilby -这要看情况。在Windows中,我们将内存泄漏视为相对严重的错误。但是,这很大程度上取决于分量。

例如,对于很少运行且运行时间有限的组件,内存泄漏不是很严重。这些组件运行,完成工作,然后退出。当它们退出时,所有内存都被隐式释放。

但是,服务或其他长期运行组件(如shell)中的内存泄漏非常严重。原因是这些bug会随着时间的推移“窃取”内存。恢复的唯一方法是重新启动组件。大多数人不知道如何重新启动服务或shell——所以如果他们的系统性能受到影响,他们就重新启动。

所以,如果你有一个泄漏-评估它的影响两种方式

你的软件和你的用户体验。 对于系统(和用户)来说,节省系统资源是非常重要的。 修复对维护和可靠性的影响。 在其他地方造成倒退的可能性。

前甲板

其他回答

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

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.

一般情况下,如果遇到无法避免的内存泄漏,则需要更加认真地考虑对象所有权问题。

但对于你的问题,我的回答是在产品代码中,是的。在开发过程中,没有。这听起来可能有些倒退,但我的理由是:

In the situation you describe, where the memory is held until the end of the program, it's perfectly okay to not release it. Once your process exits, the OS will clean up anyway. In fact, it might make the user's experience better: In a game I've worked on, the programmers thought it would be cleaner to free all the memory before exiting, causing the shutdown of the program to take up to half a minute! A quick change that just called exit() instead made the process disappear immediately, and put the user back to the desktop where he wanted to be.

但是,您对调试工具的看法是正确的:它们会突然发作,而且所有的假阳性可能会使查找真正的内存泄漏变得很痛苦。正因为如此,总是编写释放内存的调试代码,并在发布时禁用它。

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

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个字节不值得修复,所以我写了一条评论说它被泄露了,为了修复它需要改变什么,以及为什么当时不值得。

在应用程序运行后清理操作系统在概念上没有问题。

这实际上取决于应用程序以及它将如何运行。在需要运行数周的应用程序中不断发生的泄漏必须得到处理,但是一个不需要太多内存就能计算结果的小工具应该不是问题。

许多脚本语言不垃圾收集循环引用是有原因的……对于它们的使用模式,这不是一个实际的问题,因此浪费的资源和浪费的内存一样多。

最佳实践是始终释放所分配的空间,特别是在编写旨在在整个系统正常运行期间运行的内容时,即使在退出之前进行清理。

这是一个非常简单的规则。以无泄漏为目标进行编程,可以很容易地发现新的泄漏。你会卖给别人一辆你自己造的车吗?你知道它一熄火就会喷到地上?:)

清理函数中的一些if () free()调用是廉价的,为什么不使用它们呢?