我正在用 Objective-C 编写一个应用程序,我收到了这个错误:
MyApp(2121,0xb0185000) malloc: *** 对象 0x1068310 错误: double free
*** 在 malloc_error_break 中设置断点进行调试
当我释放一个 NSAutoreleasePool 并且我无法弄清楚我要释放两次的对象时,就会发生这种情况。
我如何设置他的断点?
有没有办法知道这个“对象0x1068310”是什么?
我正在用 Objective-C 编写一个应用程序,我收到了这个错误:
MyApp(2121,0xb0185000) malloc: *** 对象 0x1068310 错误: double free
*** 在 malloc_error_break 中设置断点进行调试
当我释放一个 NSAutoreleasePool 并且我无法弄清楚我要释放两次的对象时,就会发生这种情况。
我如何设置他的断点?
有没有办法知道这个“对象0x1068310”是什么?
当一个对象被“双重释放”时,最常见的原因是你(不必要地)释放了一个自动释放的对象,然后当包含的自动释放池被清空时它被自动释放。
我发现追踪额外版本的最佳方法是在 Xcode 中为受影响的可执行文件使用NSZombieEnabled环境变量。要快速了解如何使用它,请查看这个 CocoaDev wiki 页面。(除了这个页面之外,Apple 还记录了一些在 Xcode 中调试代码的非常晦涩但有用的技巧,其中一些已经多次保存了我的培根。我建议在 developer.apple.com 上查看此技术说明— 链接跳转到 Cocoa 的 Foundation 框架部分)。
编辑:您通常可以在 Xcode 调试器中跟踪有问题的对象,但如果您使用 Instruments 来帮助您,这通常会容易得多。在 Xcode 中,选择Run → Start With Performance Tool → Object Allocations,您应该能够将有问题的对象追溯到它的创建位置。(如果您如上所述启用了僵尸,这将最有效。)注意: Snow Leopard 向 Instruments 添加了一个 Zombies 工具,也可以从 Run 菜单访问。光是 29 美元就值了!;-)
还有一个相关的 SO question here。
当您中断调试器时,您会发现对象是什么。只需查找调用堆栈,您就会找到释放它的位置。这会告诉你它是哪个对象。
设置断点的最简单方法是:
- 转到运行 -> 显示 -> 断点 ( ALT- Command- B)
- 滚动到列表底部并添加符号
malloc_error_break
除了Quinn Taylor的回答,我只想添加我的经验。
在我的一个应用程序中,我必须将数据解析并保存到核心数据对象中,然后让这些对象显示在视图上。实际上,该应用程序运行良好并且根本不会崩溃,直到我尝试进行多次来回导航的压力测试,并尝试尽可能快地打开多个视图。应用程序因上述消息而崩溃。
我已经尝试了 Quinn 在他的回答中建议的所有方法,但仍然无法找出确切原因。
我设置了 NSZombieEnabled=YES 和 NSStackLogging=YES,运行命令 shell malloc_history 找出原因,但仍然没有运气。它总是指出我将数据保存到核心数据对象的位置,事实上,我已经检查了数千次过度释放的对象,没有什么奇怪的。
使用各种工具(分配、泄漏等)在仪器中运行仍然没有帮助。启用 Guard Malloc 仍然一无所获。
最后的救援:我试图回到从 Core Data 中获取对象并向所有这些对象发送保留消息的视图,并记下这些更改。解决了问题!!!
所以,我发现我没有保留一个,这正是原因。只是想分享我的经验,以便您的应用程序有另一个救援。
按 Cmd+Shift+R 打开调试器控制台。在那里,输入
break malloc_error_break
malloc_error_break
在函数的开头设置断点。
如果要找出地址 0x1068310 处的对象,可以在调试器控制台中键入以下内容:
print-object 0x1068310
当然,你必须在对象还活着的时候这样做——如果在你这样做的时候对象已经被释放了,那么这将不起作用。
对我来说,这个问题已经解决了
(gdb) call (void)_CFAutoreleasePoolPrintPools()
就在坠机之后。堆栈顶部的地址是罪魁祸首的地址。扔进去retain
,瞧。
日志消息中给出的地址没有让我到任何地方。它从未出现在任何各种乐器中。显然是指向一些已经被释放的内部数据的指针。
只是一个更新,使其与 Xcode 4 相关......
来自Xcode 4 用户指南:
添加一个符号断点。. .
- 在断点导航器的左下角,单击添加按钮。
- 选择添加符号断点。
- 在符号字段中输入符号名称。
- 单击完成。
这就是 Xcode 断点窗口中 malloc_error_break 断点的样子。需要选中复选框以使其工作。
替代文字 http://www.martijnthe.nl/wp-content/uploads/2009/08/Afbeelding-1.png
检查您的类并查看 dealloc 方法。确保你关心打电话[super dealloc].
我遇到了同样的问题,发现我正在打电话[self dealloc]
。就是不注意。
在 Xcode 中,单击行号左侧以设置断点。然后您可以通过执行“构建和调试”来启动它。
建议不要有您创建的对象,autorelease
因为内存是 iPhone 上的商品。Apple 建议明确调用release
.
通常,要查找这些类型的内存和指针问题,您需要针对Valgrind等运行时内存错误检查器运行代码。这应该能够指出你的代码做错的很多事情,除了那些导致它崩溃的事情。
Valgrind可以在 OSX 上工作(尽管它说它“不受支持、不完整和有问题”),并且通过一点黑客攻击,有人让它在iPhone SDK 可执行文件上工作。
更好的是你可以试试 Instruments,它是 XCode 的一部分。这里有一个运行它的教程。
如果malloc_error_break
没有帮助...
解决此错误的最佳方法是在打开的情况下运行仪器。NSZombies
当 Zombie 收到消息时,Instruments 会标记您,您可以直接追溯到代码行。
雪豹需要,但这是一个救星!