如何找到malloc“双重免费”错误的原因?

时间:2009-06-09 16:49:50

标签: iphone objective-c memory-management malloc autorelease

我正在用Objective-C编写一个应用程序,我收到了这个错误:

  

MyApp(2121,0xb0185000)malloc:***对象0x1068310的错误:双倍免费       ***在malloc_error_break中设置断点以进行调试

当我发布NSAutoreleasePool并且我无法弄清楚我要释放的对象时,会发生这种情况。

如何设置断点?

有没有办法知道这个“对象0x1068310”是什么?

13 个答案:

答案 0 :(得分:45)

当一个对象被“双重释放”时,最常见的原因是你(不必要地)释放了一个自动释放的对象,并且当包含自动释放池被清空时,它会在以后自动释放。

我发现追踪额外版本的最佳方法是在Xcode中对受影响的可执行文件使用 NSZombieEnabled 环境变量。要快速了解如何使用它,请查看this CocoaDev wiki page。 (除了这个页面之外,Apple还记录了一些非常模糊但有用的技巧,用于调试Xcode中的代码,其中一些已经保存了我的培根几次。我建议在developer.apple.com上查看this Technical Note。 - 链接跳转到Cocoa的Foundation框架部分。)

编辑:您经常可以在Xcode调试器中跟踪违规对象,但如果您使用Instruments来帮助您,通常会更容易。从Xcode中选择运行→使用性能工具开始→对象分配,您应该能够将有问题的对象追溯到创建它的位置。 (如上所述,如果您启用了僵尸,这将最有效。)注意: Snow Leopard将“Zombies”工具添加到“工具”,也可以从“运行”菜单访问。可能值得单独29美元! ; - )

还有related SO question here

答案 1 :(得分:37)

当你在调试器中断时,你会发现对象是什么。只需查看调用堆栈,您就会找到释放它的位置。这将告诉你它是哪个对象。

设置断点的最简单方法是:

  
      
  1. 转到“运行” - >显示 - >断点( ALT - 命令 - B
  2.   
  3. 滚动到列表底部并添加符号malloc_error_break
  4.   

答案 2 :(得分:12)

除了Quinn Taylor的答案之外,我只想补充一下我的经验。

在我的一个应用程序中,我必须解析并将数据保存到核心数据对象中,然后让这些对象显示在视图上。实际上,应用程序工作正常并且根本没有崩溃,直到我尝试进行多次来回导航的压力测试,尝试尽可能快地打开多个视图。该应用程序崩溃了以上消息。

我已经尝试了Quinn在他的回答中提出的所有方法,但仍未找出究竟原因在哪里。

我设置NSZombieEnabled = YES,并且NSStackLogging = YES,运行命令shell malloc_history找出原因,但仍然没有运气。它总是指出我将数据保存到核心数据对象的位置,事实上,我已经检查过数千次过度释放的对象,没什么奇怪的。

使用各种工具(分配,泄漏等)在仪器中运行仍然无济于事。启用Guard Malloc仍然一无所获。

最终救援:我试图回到从Core Data中获取对象的视图,并向所有这些对象发送保留消息,并注意到这些更改。它解决了这个问题!

所以,我发现我没有保留一个,这正是原因。只想分享我的经验,以便为您的应用程序再次提供帮助。

答案 3 :(得分:9)

按Cmd + Shift + R打开调试器控制台。在那里,键入

break malloc_error_break

malloc_error_break函数的开头设置断点。

如果要查找地址0x1068310处的对象,可以在调试器控制台中键入以下内容:

print-object 0x1068310

当然,你必须在对象仍然存活时执行此操作 - 如果对象在你执行此操作时已经被释放,那么这将无效。

答案 4 :(得分:4)

对我来说,这个问题已经解决了

(gdb) call (void)_CFAutoreleasePoolPrintPools()
事故发生后

。堆栈顶部的地址是罪魁祸首的地址。提出了retain和瞧。

日志消息中给出的地址并没有让我随处可见。它从未出现在任何各种仪器中。显然是指向已经释放的一些内部数据的指针。

答案 5 :(得分:4)

在Xcode 4中添加符号断点

只是更新以使其与Xcode 4相关...

来自Xcode 4 User Guide

  

添加符号断点。 。

     
      
  1. 在断点导航器的左下角,单击“添加”   按钮。
  2.   
  3. 选择添加符号断点。
  4.   
  5. 在中输入符号名称   符号字段。
  6.   
  7. 点击完成。
  8.   

答案 6 :(得分:3)

这就是malloc_error_break断点在Xcode的Breakpoints窗口中的样子。 需要选中方框才能使其正常工作。

alt text http://www.martijnthe.nl/wp-content/uploads/2009/08/Afbeelding-1.png

答案 7 :(得分:2)

检查你的类并查看dealloc方法。确保您在关注[super dealloc].

我遇到了同样的问题,发现我正在调用[self dealloc]。只是不注意。

答案 8 :(得分:1)

这通常是由一些检查员引起的,例如safari或safari预览。请参阅 post postquestion

删除AutoMatically Show Web ....的选择,将删除此问题。

注意,关闭safari或safari预览不会消除此问题。你必须取消选择safari和safari预览。

如果不这样做,请参阅此 answer post 进行调试。

deselect automatically inspect on safari preview

答案 9 :(得分:1)

请找到以下步骤,了解如何查找免费的对象并使应用程序崩溃。

  

1)单击“断点导航器”。
2)然后单击   “ + ”按钮位于下方。
3)添加“符号   断点...... “从列表中。”4)添加   “符号”选项中的“ malloc_error_break ”关键字。

或者您也可以参考下面的GIF演示文稿。

GIF represenation

答案 10 :(得分:0)

在Xcode中,单击行号左侧以设置断点。然后,您可以通过执行“构建和调试”来启动它。

建议不要将您创建的对象设为autorelease,因为内存是iPhone上的商品。 Apple建议明确调用release

答案 11 :(得分:0)

要查找这些类型的内存和指针问题,您希望针对运行时内存错误检查程序(如Valgrind)运行代码。这应该能够指出你的代码做错的很多事情,除了那些导致它崩溃的事情。

Valgrind can work on OSX(虽然它说它“不受支持且不完整且有错误”),并且有点骇客,有人让它在iPhone SDK executables上工作。

更好的是你可以尝试仪器,这是XCode的一部分。有一个运行它的教程here

答案 12 :(得分:0)

如果malloc_error_break没有帮助......

解决此错误的最佳方法是在启用NSZombies的情况下运行乐器。当僵尸被发送消息时,仪器将标记您,并且您可以直接追溯到代码行。

雪豹需要,尽管如此救命!