代码之家  ›  专栏  ›  技术社区  ›  jasonh

在xcode中中断exc-bad-access?

  •  45
  • jasonh  · 技术社区  · 15 年前

    我是iPhone开发和Xcode的新手,不知道如何开始排除 EXC_BAD_ACCESS 信号。如何让Xcode在导致错误的确切行中断?


    我似乎无法让xcode在导致问题的行上停止,但我在调试控制台中确实看到了以下行:

    太阳10月25日15:12:14 JasonsMacBook 测试项目[1289]: CGContextSetStrokeColorWith颜色: 无效上下文

    太阳10月25日15:12:14 JasonsMacBook 测试项目[1289]: cgContextSetLineWidth:上下文无效

    太阳10月25日15:12:14 JasonsMacBook 测试项目[1289]: CGContextAddPath:上下文无效

    太阳10月25日15:12:14 JasonsMacBook 测试项目[1289]: CGContextDrawPath:上下文无效

    2009年10月25日15:12:14.680 兰德斯特[1289:207]***-[CFarray objectatindex::消息发送到 释放实例0x3c4e610

    现在,我正试图从中提取上下文 UIGraphicsGetCurrentContext() 然后传递到我要绘制的对象。


    进一步的尝试和错误调试,我发现 NSMutableArray 我的课上有一处房产是僵尸。我走进了 init 类的函数,下面是我使用的代码:

    if ((self = [super init])) {
            NSMutableArray *array = [NSMutableArray array];
            self.terrainBlocks = array;
            [array release];
        }
        return self;    
    }
    

    我删除了 [array release] 线,它不再给我 Excel BADIAccess 信号,但我现在对这项工作的原因感到困惑。我想,当我使用财产时,它会自动为我保留它,因此我应该从内部释放它。 初始化 这样我就不会漏了。我完全搞不清楚这是如何工作的,所有的指南和stackoverflow问题我都只读过,更搞不清楚如何在init方法中设置属性。关于哪种方式最好,似乎没有一致意见。

    10 回复  |  直到 8 年前
        1
  •  84
  •   Nicholas Riley    15 年前

    对于任何exc_bad_访问错误,您通常尝试向已发布的对象发送消息。这个 最好的 找到这些的方法是使用 NSZombieEnabled .

    这项工作从未真正释放过一个对象,而是将它包装成一个“僵尸”,并在其中设置一个标志,表示它通常会被释放。这样,如果您再次尝试访问它,它仍然知道在您犯错误之前是什么,并且有了这一点信息,您通常可以回溯查看问题是什么。

    它在后台线程中尤其有用,因为调试器有时会把有用的信息放在外。

    需要注意的是 但是,您需要100%确保这只存在于调试代码中,而不存在于分发代码中。因为从来没有发布过任何东西,你的应用程序会泄漏,泄漏和泄漏。为了提醒我执行此操作,我将此日志放在AppDelegate中:

    if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled"))
      NSLog(@"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!");
    

    如果需要帮助查找确切的行,请执行生成和调试( 命令-Y )而不是构建和运行( CMD—R )当应用程序崩溃时,调试器将精确地显示哪一行,并与nszombieEnabled结合使用,您应该能够找到确切的原因。

        2
  •  17
  •   epatel    15 年前

    关于你的阵列。线

    NSMutableArray *array = [NSMutableArray array];
    

    实际上不会给您一个保留对象,而是一个自动释放对象。它可能会保留在下一行中,但是您不应该在第三行中释放它。见 this

    这是基本规则:

    如果使用名称以__alloc_157;或__new_157;或包含__copy_157;(例如,alloc、new object或mutablecopy)开头的方法创建对象,或者如果发送保留消息,则获得该对象的所有权。您负责使用release或autorelease放弃您拥有的对象的所有权。其他任何时候你收到一个物体,你都不能释放它。

        3
  •  10
  •   snez    13 年前

    在Xcode4中,您可以通过单击“方案”下拉列表(左上角,停止按钮旁边的右上角)->编辑方案->诊断选项卡->启用僵尸对象来启用僵尸。

        4
  •  7
  •   Darren    15 年前

    xcode/gdb总是中断 EXC_BAD_ACCESS ,您只需要在调用堆栈中查找触发它的代码。

    请注意,这些类型的错误通常发生在 autoreleased 对象,这意味着问题的最终原因不在触发的调用堆栈中 Excel BADIAccess . 这时nszombieEnabled和nsautoreleasefreedObjectCheckEnabled变得有用。

        5
  •  5
  •   Jonathan Moffatt    13 年前

    一条旧线索的新答案…在Xcode4中,诊断Exc_Bad_访问异常的最有效方法是使用工具来分析应用程序(从Xcode单击产品/配置文件并选择僵尸)。这将帮助您识别发送到已释放对象的消息。

        6
  •  2
  •   Adam Eberbach Adil Shaikh    15 年前

    来自斯坦福CS193P类:如果为符号添加断点(手动,通过编辑断点) objc_exception_throw 您可以更好地了解出什么地方出了问题——让事情继续进行到调试器本身停止的程度,这会使事情变得模糊,并破坏堆栈跟踪。当您在objc_Exception_Throw中停止时,您可以经常回顾一下访问/操作到底是什么导致了您的问题。

        7
  •  2
  •   Frank    15 年前

    另一种有用的方法是设置断点,该断点将在异常发生后直接触发:

    打开“断点”窗口(运行“显示断点”),并添加两个名为“objc”和“objc”的符号断点exception“throw”和“nsexception raise”“

    来自: http://blog.emmerinc.be/index.php/2009/03/19/break-on-exception-in-xcode/

        8
  •  1
  •   Centurion    13 年前

    只想为来自网络的其他人添加,搜索相同错误但有不同错误的解决方案。在我的例子中,当我试图用键名中的拼写错误来实例化nsdictionary时,我得到了相同的错误,我忘记在键前面添加“@”:

    NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys: myObj1, @"goodKey", myObj2, "badkey @ is missing in front", nil];
    
        9
  •  1
  •   Thomas Allenbaugh    8 年前

    我希望我没有错过相同的答案,但我发现有些项目可能会因为在旧的iOS版本的模拟器上运行而抛出此错误,因为旧版本的iOS版本可能与项目依赖项或框架不兼容。我花了很长时间才意识到它只是在老式的模拟器版本中发生的,比如iPhone4S,这个应用程序甚至不应该尝试支持。

    如果能得到一条更详细的错误消息就好了,但是我想这是它起源的框架的责任……无论如何,这是一个相当常见的搜索登陆,也许这能帮助一些人像我自己一样严重地在网上偷懒。

        10
  •  0
  •   user2387149 Anurag Soni    11 年前

    在启用僵尸之前,我建议首先清除所有警告(如果有)。简单的事情,比如一个没有 return 可能导致此错误。如果没有警告,按照其他答案的建议继续。