iPhone开发 - 没有堆栈跟踪的EXC_BAD_ACCESS错误

时间:2009-01-22 09:58:57

标签: cocoa-touch

这是我的情况:我有一个显示联系人的表格视图。导航栏中的“添加”按钮用于加载另一个数据输入视图。这个新视图在表头中有图像,每个表格单元格都有 UITextField UITextView 。当我按下取消时,弹出视图并释放内存。

这是我的问题:当我打开“添加”界面时,在任何UITextField或UITextView中提供一个值,然后按“取消”返回到父视图,我得到一个 EXC_BAD_ACCESS 错误。当我跟踪它时,“添加控制器”正确调用dealloc,但在 [super dealloc] 之后,当我按下Continue时,它会抛出此错误。只是这个,没有跟踪,虽然我正在使用 NSZombieEnabled。当我用Instruments运行代码时,我没有收到任何错误:(

我希望我能解释这个问题。有什么指针吗?感谢。

6 个答案:

答案 0 :(得分:8)

此错误的最常见原因是当您释放对象时,某些其他机制会在以后尝试访问/释放/释放它。

每当我收到EXC_BAD_ACCESS错误的报告时,我的第一个建议是逐步执行代码以确定导致它的行,然后搜索引用该行的任何显式[object release]调用宾语。逐一评论它们以找出您可能出错的地方(当然,确保该对象稍后正确发布)。

如果该行无法帮助您找出导致问题的对象,请开始查看[object release]次调用,并确保您没有意外释放对象太多次,或释放你不拥有的物品。

这导致了关于Objective-C中release的一般指南:

  

如果您拥有一个对象(分配或保留它),则将其释放。如果您不拥有它(通过便利方法或其他人分配它),您不会释放它。

(通过Memory Management with Objective C / Cocoa / iPhone,也有一些很好的提示。)

答案 1 :(得分:6)

虽然这通常是内存管理不善的结果,但可能由于其他原因而发生(并且比简单地打开NSZombieEnabled更难调试)。例如,如果您未能为格式字符串提供正确数量的参数(即在调试NSLog的另一个问题时),即使启用了所有调试参数,也可能最终没有堆栈跟踪。幸运的是,您可以在Xcode中使用GDB restore the stack trace to a previous state

在GDB控制台中,您应该看到崩溃程序的指令。找到失败之前的最后一条成功返回指令。看起来应该是这样的:

je    0x986cef35 <objc_msgSend+117>

注意十六进制值并在GDB中执行以下操作:

set $eip = 0x986cef35
stepi
where

你应该(希望)现在有更多信息量的堆栈跟踪。

Source(与上面的链接相同)

答案 2 :(得分:4)

Cameron Spickert的回答有点弃用,因为Xcode现在使用lldb而不是gdb。源文章的链接也已经死了。

使用以下lldb命令可以完成同样的事情:

(lldb) thread backtrace

这将显示当前线程的bt。如果你想改变你想从中得到bt的线程,选择框架并得到它:

(lldb) thread list
(lldb) thread select 2
(lldb) thread backtrace

如果您想复制Cameron Spickert答案的确切行为,请使用以下命令:

(lldb) expr unsigned int $eip = 0x1979c81d4
(lldb) stepi
(lldb) thread backtrace

Source 1

Source 2

答案 3 :(得分:3)

将[super dealloc]作为类dealloc方法的最后一个语句。当你首先解除超级类时,你会得到这种行为。

答案 4 :(得分:1)

一般的经验法则是您创建的任何内容,您需要管理(保留/释放)。任何来自NIB的东西通常都不应该在代码中发布。

答案 5 :(得分:1)

上述不应释放NIB对象的陈述与Apple相矛盾:请参阅here,其中说明您有出口的对象应该以dealloc发布,并且您应该确保之后将对象引用设置为nil。

免责声明:我是一名iPhone编程新手,虽然已经编程了很长时间。