我刚开始在C ++中尝试使用SDL,我认为定期检查内存泄漏可能是早期形成的好习惯。
考虑到这一点,我一直在通过Valgrind运行我的'Hello world'程序以捕获任何泄漏,尽管除了最基本的SDL_Init()
和SDL_Quit()
语句之外我已经删除了所有内容, Valgrind仍然报告丢失了120个字节,仍然可以达到77k。
我的问题是:内存泄漏是否有可接受的限制,或者我应该努力使我的所有代码完全无泄漏?
答案 0 :(得分:17)
小心Valgrind在测量中没有发现误报。
许多内存分析器的天真实现将丢失的内存标记为泄漏,当它不是真的时。
也许可以阅读Wikipedia article on Purify的外部链接部分中的一些论文。我知道Purify附带的文档描述了几种情况,在尝试检测内存泄漏时会出现误报,然后继续描述Purify用于解决问题的技术。
BTW我不以任何方式与IBM有任何关系。我已经广泛使用了Purify,并保证其有效性。
编辑:这是一个涵盖内存监控的excellent introductory article。这是Purify的具体内容,但对内存错误类型的讨论非常有趣。
HTH。
欢呼声,
罗布
答案 1 :(得分:11)
你必须小心“内存泄漏”的定义。在第一次使用时分配一次并在程序退出时释放的东西有时会被泄漏检测器显示,因为它在第一次使用之前开始计数。但这不是泄漏(虽然它可能是糟糕的设计,因为它可能是某种全球性的。)
要查看给定的代码块是否泄漏,您可以合理地运行一次,然后清除泄漏检测器,然后再次运行(这当然需要对泄漏检测器进行编程控制)。每次运行程序“泄漏”的事情通常无关紧要。每次执行时“泄漏”的事情通常最终都很重要。
我很少发现在这个指标上达到零很难,这相当于观察蠕变内存使用而不是丢失块。我有一个库,它有如此繁琐,有缓存和UI家具等等,我只是运行我的测试套件三次,并忽略任何“泄漏”,这不会发生在三个块的倍数。我仍然抓住了所有或几乎所有真正的泄漏,并分析了棘手的报告,一旦我得到了悬而未决的果实。当然,为此目的使用测试套件的缺点是:(1)您只能使用不需要新进程的部分,以及(2)您发现的大多数泄漏都是测试代码的错误,而不是图书馆代码...
答案 2 :(得分:11)
生活中的内存泄漏(和其他粗心的问题),在最好的情况下,(在我看来)非常糟糕的编程。最坏的情况是它使软件无法使用。
您应该首先避免引入它们并运行您和其他人提到的工具来尝试检测它们。
避免草率编程 - 已经有足够的坏程序员 - 世界上不需要另外一个。
修改
我同意 - 许多工具可以提供误报。
答案 3 :(得分:8)
如果你真的担心内存泄漏,你需要做一些计算。
您需要测试您的应用程序,如一小时,然后计算泄漏的内存。这样,您就会得到泄漏的内存字节/分钟值。
现在,您需要估算程序会话的平均长度。例如,对于notepad.exe,15分钟听起来对我来说是一个很好的估计。
如果(平均会话长度)*(泄漏字节数/分钟)> 0.3 *(通常由您的进程占用的内存空间),那么您应该做更多的努力来减少内存泄漏。我只是编了0.3,用常识来确定你可以接受的门槛。
请记住,作为程序员的一个重要方面是作为软件工程师,而工程师通常会选择两个或更多不良选项中最差的选项。当你需要衡量实际选项的糟糕程度时,数学总是很方便。
答案 4 :(得分:7)
对于桌面应用程序,小内存泄漏不是一个真正的问题。对于服务(服务器),不能接受内存泄漏。
答案 5 :(得分:6)
大多数操作系统(包括Windows)将在卸载程序时返回程序所分配的所有内存。这包括程序本身可能已丢失的任何内存。
鉴于此,我通常的理论是在启动期间泄漏内存是完全正常的,但不可以在运行时执行此操作。
所以真的问题不在于你是否泄漏任何内存,如果你在程序的运行时间内不断泄漏它。如果你使用你的程序一段时间,无论你做什么,它都会丢失120个字节而不是增加,我会说你做得很好。继续前进。
答案 6 :(得分:2)
这取决于您的申请。一些泄漏可能是不可避免的(由于找到泄漏最后期限所需的时间)。只要您的应用程序可以在您想要的时间内运行,并且在那段时间内不会占用大量内存,那么它可能很好。
答案 7 :(得分:2)
看起来SDL开发人员看起来并不使用Valgrind,但我基本上只关心丢失的120个字节。
嗯,有了Valgrind,“仍然可以访问的内存”往往不是真正泄露的内存,尤其是在这么简单的程序中。我可以安全地打赌,SDL_Quit()基本上没有分配,所以“泄漏”只是SDL_Init()分配一次的结构。考虑到这一点,我一直在通过Valgrind运行我的'Hello world'程序以捕获任何泄漏,虽然我已经删除了除最基本的SDL_Init()和SDL_Quit()语句之外的所有内容,但Valgrind仍然报告120字节丢失,77k仍然可以访问。
尝试添加有用的工作,看看这些数量是否增加;尝试制作一个有用的工作循环(比如创建和销毁某些SDL结构),看看泄漏量是否会随着迭代次数的增加而增加。在后一种情况下,您应该检查泄漏的堆栈跟踪并修复它们。
否则,那些77k泄漏计为“应该在程序结束时释放的内存,但是他们依靠OS来释放它。”
所以,实际上,我现在更担心的是这120个字节,如果它们不是误报,它们通常很少。 Valgrind的误报主要是使用未初始化内存的情况(例如,因为它实际上是填充)。
答案 8 :(得分:1)
根据Rob Wells对Purify的评论,下载并试用其他一些工具。我使用BoundsChecker和AQTime,多年来都看到了不同的误报。请注意,内存泄漏也可能存在于第三方组件中,您可能希望从分析中排除该组件。例如,MFC在第一个视图版本中有许多内存泄漏。
IMO,应该跟踪任何进入可能具有较长使用寿命的代码库的代码的内存泄漏。如果您无法跟踪它们,请至少记下它们是否存在于同一代码的下一个用户。
答案 9 :(得分:1)
Firstable内存泄漏只是一个严重的问题,当它们随着时间的推移而增长,否则应用程序看起来只是从外面看起来更大(显然这里也有一个限制,因此'严重')。 当您的泄漏随着时间的推移而增长时,您可能会遇到麻烦。但是,有多少麻烦取决于具体情况。如果你知道内存的去向,并且可以确保你总是有足够的内存来运行程序和该机器上的其他所有东西,你仍然可以。 如果你不知道记忆的去向,我不会发送程序并继续挖掘。
答案 10 :(得分:1)
特别是在Linux上使用SDL,底层的X windows库似乎有些漏洞。对于那些你无能为力(除非你想尝试修复库本身,这可能不适合那些胆小的人)。
你可以使用valgrind的抑制机制(参见valgrind手册页中的--supsressions和--gen-suppressions)告诉它不要打扰你这些错误。
总的来说,我们必须对第三方图书馆稍微宽容一点;虽然我们绝对不应该接受我们自己的代码中的内存泄漏,并且在替代第三方库之间进行选择时,内存泄漏的存在应该是一个因素,有时别无选择,只能忽略它们(尽管报告它们可能是个好主意)到图书馆维护者。)