提问人:Luchian Grigore 提问时间:3/29/2012 最后编辑:CommunityLuchian Grigore 更新时间:3/29/2012 访问量:742
对动态分配的对象不调用 delete 是否始终是内存泄漏?
Is not calling delete on a dynamically allocated object always a memory leak?
问:
从这里开始的讨论中,我想知道以下代码是否存在内存泄漏:
int main()
{
new int();
//or
int* x = new int();
return 0;
}
我知道内存作系统回收了,但无论如何都是泄漏吗?我相信是的。
内存泄漏的定义是什么?我只能在标准中找到一个参考,它不是很有帮助。
编辑:我不想开始辩论 - “我认为......”不是我要找的那种答案。我最感兴趣的是来源 - C++书籍或网站或任何关于它的内容。
答:
我会这样定义内存泄漏
a) 它需要内存
b) 它对应用程序不再有用
c) 它不再可访问,因此不再可删除
据此,我会判断您的样本为内存泄漏。 您的样品显示非严重泄漏。 一个严重的泄漏是持续占用内存,在应用程序崩溃之前可能发生什么
上面的代码确实存在泄漏。然而,更重要的是,如果你没有分配一个 ,你分配了一个特殊的对象,比如一个服务器连接对象,如果你从来没有正确地清理和调用,该对象的析构函数永远不会运行,如果你的服务器连接需要执行特殊的清理代码(写入文件等),这可能很重要。int
delete
在您的特定示例中,泄漏无关紧要,因为 main 立即退出(有效)并且内存被释放回操作系统。但是,在编写生产代码时,您绝对不应该留下任何泄漏(即使是像上面这样微不足道的泄漏),因为代码可能会被移动到不同的函数中,并且泄漏实际上可能会在程序生命周期中传播。
此外,也许要考虑的最重要的事情是程序员认为是内存泄漏。您应该将内存视为一种资源,应根据自己的模型进行管理。请考虑阅读本文,其中讨论了一些资源分配和管理模型。考虑 RAII(资源获取即初始化)和智能指针(或者至少是智能指针的概念和引用计数的概念)。
评论
是的,存在 4 个字节的泄漏,因为分配的内存不是 d,并且在应用程序的生命周期内它是泄漏。new
delete
从这个链接:
http://www.yolinux.com/TUTORIALS/C++MemoryCorruptionAndMemoryLeaks.html
Memory leak description: Memory is allocated but not released causing an application to consume memory reducing the available memory for other applications and eventually causing the system to page virtual memory to the hard drive slowing the application or crashing the application when than the computer memory resource limits are reached. The system may stop working as these limits are approached.
评论
这是主观的/值得商榷的。
在我看来,有两个级别的资源(内存是操作系统提供的资源之一)泄漏:操作系统级别和应用程序级别。请注意,名称是自定义的,可能有更合适的技术术语。
一旦应用程序终止,应用程序级泄漏将不复存在,因为操作系统会清理应用程序的混乱。也就是说,一旦应用程序被核弹,对操作系统稳定性的威胁就消失了。在体面的操作系统上,应用程序中的内存分配只能产生“应用程序级”泄漏。
一旦应用程序终止,操作系统级泄漏就不会停止存在。通常,其他一些资源属于该类别(文件),但不属于内存。但是,我不能保证没有操作系统/平台不清理泄漏的内存。根据墨菲定律,即使在今天,也可能有这样的平台在使用。
因此,当我说/写“内存泄漏”时,我说的是应用程序级泄漏 - 任何未被 APP 显式删除的内存分配。每一次分配,即使是有意的,都属于类别。此外,通常内存分配分析器和类似工具会抱怨您的“故意泄漏”,
所以,是的,你的代码有泄漏。
在我看来,即使你确定操作系统会释放它们,即使是故意泄漏也是一个坏主意,因为它鼓励草率的编码,有一天你将无法删除在其析构函数中释放某些东西的类,操作系统无法自动清理。鉴于普通 PC 上 Windows 注册表和临时文件夹中剩余的垃圾数量,许多程序员经常将该技术用于操作系统未正确清理的资源。因此,最好的主意是避免泄漏。
评论
第二种情况不是内存泄漏。
这不是泄漏,因为您仍然有一个指向已分配内存的指针。
为了定义内存泄漏,我想坚持定义大多数内存分析工具(如 valgrind)使用的定义:
内存已分配,随后无法释放,因为程序不再具有指向已分配内存块的任何指针。
评论
objects inaccessible by running code but still stored in memory
main
这取决于您如何定义“泄漏”。根据最明显的 定义,也是唯一有用的定义,它不是泄漏,至少在 应用程序级别。桶不会因为您故意泄漏而泄漏 允许有限量的水逸出。实际上, 应用程序不会因为有意允许绑定集而失败 的对象在程序结束之后持续存在。
关于内存泄漏,我们对这个词的看法是 由“泄漏检查器”着色---如 Purify 或 Valgrind 等程序。他们 作用是找到泄漏(除其他外),但他们没有办法 知道什么是故意的,什么是无意的,什么是有约束力的,以及什么 不是。因此,他们发明了其他定义:无法触及的对象 已经“泄露”(在实际代码中很有可能是 true),或者在执行完所有 静态对象的析构函数已被执行“泄露”。在 后一种情况,定义显然是错误的,而且有点 无用。但是有足够多的情况,这样的事情是泄漏的,它 至少警告它们(“可能的泄漏”)是合理的,前提是 有一种方法可以过滤掉特定情况。(净化和 Valgrind 认识到并非所有这些案例都是真正的泄漏,并且 提供各种过滤机制来检测它们。所有这些 很好,很好——我很高兴我们有这样的工具——但是 我们不应该允许他们歪曲语言。
最后提醒一下:标准说标准 iostream
对象(等)永远不会被破坏。所以任何缓冲区
他们分配将(可能)永远不会被释放。当然没有人在他们的
正确的头脑会考虑这些“泄漏”。std::cout
评论