我正在用C ++编写一个游戏引擎,它也支持Lua。
我最大的恐怖:内存泄漏。
这并不像我的游戏已经被他们感染了,我很害怕它们像蘑菇一样从地面冒出来,当开发处于后期阶段并且项目庞大而复杂时。
我害怕他们,因为他们似乎很难找到我。尤其是在复杂系统中。如果我的引擎差不多完成,游戏就会运行,内存就会消失,我该怎么办?我将从哪里开始搜索?
答案 0 :(得分:36)
如何找出内存泄漏的位置?
答案 1 :(得分:17)
原始指针只是导致内存泄漏的一个潜在原因。
即使您使用智能指针(如shared_ptr),如果您有一个循环,也可能会出现泄漏 - 解决此问题的方法是在某处使用weak_ptr来打破循环。使用智能指针并不能解决内存泄漏问题。
您还可以忘记基类中的虚拟析构函数,并以此方式获取泄漏。
即使没有删除新ed对象也没有问题,由于地址空间碎片,长时间运行的进程可能会增长(并且似乎会泄漏)。
像valgrind这样的工具对于查找泄漏非常非常有用,但它们并不总能告诉你修复的位置(例如,在循环或对象保持智能指针的情况下)
答案 2 :(得分:13)
需要一个定义良好的“对象生命周期”模型。无论何时你做“新”,你都需要考虑
谁拥有这个堆对象?即谁负责维护此指针并允许其他“客户”引用它?
谁负责删除此对象?这通常是#1,但不一定。
此对象的客户端的生命周期是否长于此对象的客户端?如果这是真的,并且它们实际上正在存储这个堆指针,它将取消引用不再“存在”的内存。您可能需要添加一些通知机制或重新设计“对象生命周期”模型。
很多时候你修复了内存泄漏问题,但后来遇到问题#3。这就是为什么在编写太多代码之前最好考虑一下对象生命周期模型。
答案 3 :(得分:10)
你从不使用原始指针来对抗内存泄漏。如果你有使用原始指针的代码,重构。
答案 4 :(得分:7)
答案 5 :(得分:6)
AFAIK Valgrid只是Linux
对于Windows,您有BoundsChecker和Purify等工具
如果您使用的是Visual Studio,那么C运行时库(CRT)也提供了一个非常简单且有用的工具,可用于查找开箱即用的内存泄漏。阅读_CrtDumpMemoryLeaks及其相关函数和宏
它基本上允许您在进程退出时获取内存泄漏的索引转储,然后允许您在分配泄漏内存的时间设置断点,以确切了解它何时发生。这与大多数其他工具形成鲜明对比,这些工具只能为您提供事后分析,而无法重现导致内存泄漏的事件。
从第一天开始使用这些小宝石可以让您相对安心,保持良好的状态。
答案 6 :(得分:4)
我对内存泄漏的恐惧是否合理?
如果您正在编写包含它们的代码,那么绝对是。
如何找出内存泄漏的位置?
通过分析代码。
今天是不是有很好的工具可以帮助找到内存泄漏的来源?
是的,但这仍然不容易。
好消息是,通过适当的设计完全没有必要。一盎司的预防值得大量治疗:处理内存泄漏的最佳策略是以保证不存在任何内容的方式编写代码。
答案 7 :(得分:3)
冒着听起来像我可能是自鸣得意的混蛋的风险,考虑使用 1979之后开发的任何编程语言,它没有内存泄漏问题,堆损坏堆栈损坏,甚至内存管理。 (任何说“我需要我的程序要快”的人可能从未听说过Donald Knuth。)
答案 8 :(得分:2)
内存泄漏并不太可怕 - 但它们可能对程序的性能有害(所以摆脱它们!)。
答案 9 :(得分:2)
至少对于Lua部分,您可以使用自己的内存分配器并跟踪所有分配和释放,从而发现任何内存泄漏。
答案 10 :(得分:1)
有各种跟踪内存泄漏的技术。
最简单的方法是使用一个宏和一个特定的分配器来存储分配它的函数。这样,您可以跟踪每个分配,并查看哪些分配不应该删除。然后你可以开始编写unittest并断言已经释放了内存。
如果您一直使用预编译的容器,这将不起作用,因为所有分配都将在容器中。那你的选择是:
可能有更多选择。如果您的设计允许,测试和使用自定义全局新/删除覆盖(可以查询)应该是有用的。
另外,请参阅Electronic Arts STL C++ paper,了解在STL / C ++中需要做些什么来支持正确的游戏开发。 (它可能比你的引擎更硬一点,但它肯定包含许多灵感和独创性。)
答案 11 :(得分:1)
如何找出内存泄漏的位置?
Visual Leak Detector for Visual C ++ 2008/2010