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

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

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

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


当前回答

我想你已经回答了自己的问题。最大的缺点是它们如何干扰内存泄漏检测工具,但我认为这个缺点对于某些类型的应用程序来说是一个巨大的缺点。

我使用的遗留服务器应用程序应该是坚如磐石的,但它们有泄漏,并且全局变量确实妨碍了内存检测工具。这是件大事。

在杰瑞德·戴蒙德(Jared Diamond)的《崩塌》(Collapse)一书中,作者想知道那个人在想什么,他砍倒了复活节岛上的最后一棵树,而这棵树是他建造独木舟离开该岛所需要的。我想知道许多年前第一个全局变量被添加到我们的代码库的那一天。那是它应该被抓住的日子。

其他回答

我完全同意JohnMcG的观点,只是想补充一点,我自己也有问题,无法及时发现真实的、潜在的严重内存泄漏,只是因为人们已经接受了良性的内存泄漏。随着时间的推移,这些病毒变得如此之多,在大量的良性病毒中发现严重病毒就变得越来越困难。

因此,至少为了你的程序员同事(也是为了你自己的未来),请尽快消除它们。

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

我在高中上过一门C课,老师说当你malloc的时候一定要确保自由。

但是当我在大学里上另一门课的时候,教授说对那些只运行一秒钟的小程序不免费是可以的。 因此,我认为这不会损害您的程序,但免费提供强大、健康的代码是一种很好的实践。

许多人似乎都有这样的印象:一旦释放内存,它就会立即返回到操作系统,可以被其他程序使用。

这不是真的。操作系统通常以4KiB页面管理内存。malloc和其他类型的内存管理从操作系统获取页面,并在它们认为合适的时候对它们进行子管理。free()很可能不会将页面返回给操作系统,前提是您的程序稍后会误用更多内存。

我并不是说free()从不将内存返回给操作系统。这是有可能发生的,特别是当您正在释放大量内存时。但这并不能保证。

重要的事实是:如果不释放不再需要的内存,那么进一步的malloc必然会消耗更多的内存。但是如果先释放,malloc可能会重新使用释放的内存。

这在实践中意味着什么?这意味着如果你知道你的程序从现在开始不再需要更多的内存(例如它在清理阶段),释放内存就不是那么重要了。但是,如果程序稍后可能分配更多内存,则应该避免内存泄漏——特别是那些可能重复发生的内存泄漏。

关于为什么在终止前释放内存是不好的,请参阅这条评论了解更多细节。

评论者似乎不理解调用free()并不会自动允许其他程序使用释放的内存。但这就是这个答案的全部意义!

因此,为了说服人们,我将演示一个例子,其中free()没有什么好处。为了便于计算,我假设操作系统以4000字节的页面管理内存。

Suppose you allocate ten thousand 100-byte blocks (for simplicity I'll ignore the extra memory that would be required to manage these allocations). This consumes 1MB, or 250 pages. If you then free 9000 of these blocks at random, you're left with just 1000 blocks - but they're scattered all over the place. Statistically, about 5 of the pages will be empty. The other 245 will each have at least one allocated block in them. That amounts to 980KB of memory, that cannot possibly be reclaimed by the operating system - even though you now only have 100KB allocated!

另一方面,您现在可以malloc() 9000多个块,而不会增加程序占用的内存量。

即使free()在技术上可以将内存返回给操作系统,它也可能不会这样做。Free()需要在快速操作和节省内存之间取得平衡。此外,一个已经分配了大量内存然后释放它的程序很可能会再次这样做。web服务器需要处理一个又一个的请求——保持一些“松弛”的可用内存是有意义的,这样你就不需要一直向操作系统请求内存了。

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

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

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