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

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

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

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


当前回答

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

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)。

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

理论上没有,实际情况要视情况而定。

这实际上取决于程序处理了多少数据,程序运行的频率以及它是否持续运行。

如果我有一个快速程序,读取少量数据进行计算并退出,那么就永远不会注意到一个小的内存泄漏。因为程序不会运行很长时间,并且只使用少量的内存,所以当程序存在时,泄漏将很小并被释放。

另一方面,如果我有一个处理数百万条记录并运行很长时间的程序,一个小的内存泄漏可能会在足够的时间内使机器停机。

对于有泄漏的第三方库,如果它们导致问题,要么修复库,要么找到更好的替代方案。如果不造成问题,这真的重要吗?

随着时间的推移,我看到的“良性”泄漏的数量一只手就能数得过来。

所以我的答案是肯定的。

An example. If you have a singleton resource that needs a buffer to store a circular queue or deque but doesn't know how big the buffer will need to be and can't afford the overhead of locking or every reader, then allocating an exponentially doubling buffer but not freeing the old ones will leak a bounded amount of memory per queue/deque. The benefit for these is they speed up every access dramatically and can change the asymptotics of multiprocessor solutions by never risking contention for a lock.

我已经看到这种方法在具有非常明确的固定计数的事情上有很大的好处,例如每cpu工作窃取deques,并且在Hans Boehm的C/ c++保守垃圾收集器中用于保存单例/proc/self/maps状态的缓冲区中有较小的程度,用于检测根集等。

虽然从技术上讲这是一个漏洞,但这两种情况在大小上都是有限制的,并且在可增长的循环工作窃取deque情况下,可以获得巨大的性能优势,以换取队列内存使用量增加2的有界因子。

我相信,如果你有一个程序,它将运行几秒钟,然后退出,这是可以的,它只是为个人使用。一旦程序结束,任何内存泄漏都会被清除。

当你有一个运行很长时间的程序并且用户依赖它时,问题就来了。另外,让你的程序中存在内存泄漏是一种坏的编码习惯,特别是如果它们可能在某一天将代码转换为其他内容的话。

总之,最好删除内存泄漏。

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

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

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.

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