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

在目标C和Xcode中引发调试异常

  •  10
  • rtemp  · 技术社区  · 15 年前

    我是一个长期的微软开发人员,我对使用Xcode开发iPhone是个新手。所以,我正在读一本书,并通过一些例子来教自己如何使用Objective-C编写iPhone应用程序。到目前为止,一切都很好,不过,有一段时间我遇到了通用的 objc_exception_throw '运行时的消息。当这种情况发生时,很难找到这个异常的来源。经过反复试验,我找到了我的答案。其中一个参数拼写错误。

    正如您在下面看到的,我省略了第二个“t”in按钮,拼写错误了“OtherButtonTitles”参数。

    UIAlertView *alert = [[UIAlertView alloc] 
                          initWithTitle:@"Date and Time Selected" 
                          message:message 
                          delegate:nil
                          cancelButtonTitle:@"Cancel"
                          otherButonTitles:nil];
    

    我花了很多时间才找到的原因是代码构建成功。这是Objective-C编译器的正常行为吗?我习惯了在.NET编译器中,当我出现这样的常见语法错误时,生成会失败。当我犯这些错误时,是否可以更改编译器设置以使构建失败?

    5 回复  |  直到 14 年前
        1
  •  25
  •   lhunath    15 年前

    首先,打开 ~/.gdbinit (这就是文件 .gdbinit 在您的主目录中-是的,从一个点开始),并将其放入其中:

    fb -[NSException raise]
    fb objc_exception_throw
    fb malloc_error_break
    

    这将使用三个默认断点初始化gdb,当它们发生时,gdb将停止应用程序并向您显示堆栈跟踪。这与Xcode集成得非常好,所以一旦某个异常发生或malloc失败,您就可以通过单击堆栈跟踪元素来很好地浏览代码。

    然后,打开 Get Info 项目面板(或选择项目 Groups & Files 击中 cmd-i ) Build 选项卡并设置项目的 Base SDK Device - iPhone OS [someversion] . 一直滚动到底部,找到 GCC 4.0 - Warnings 部分。在那里;打开你觉得舒服的警告,但一定要打开 Treat Warnings as Errors (这相当于 GCC_TREAT_WARNINGS_AS_ERRORS )就我个人而言,我将它设置为:

    GCC Warning Build Settings http://lhunath.lyndir.com/stuff/gcc_warnings.png

    您现在应该会收到编译器警告,因为您在代码中可能会做错误的大多数事情,并且编译器不会让您运行代码,直到您修复它们。当事情经过编译器的鼻子时,您应该能够在一个方便的地方轻松地发现gdb中断的问题。

    你也应该调查一下 NSZombie* . 这些是环境变量,对于早期破坏坏的内存分配或访问情况非常方便。例如;wih NSZombieEnabled 不会真正释放任何内容;在DealLoc上,它将被覆盖 _NSZombie 如果您再次尝试访问这个解除锁定的内存(解除对解除锁定的指针的引用),您将在gdb中得到一些中断的东西,而不是像正常一样进行的调用,只在随机数据上发出(当然,这不是您想要的)。有关详细信息,请参阅 http://www.cocoadev.com/index.pl?NSZombieEnabled .

        2
  •  9
  •   Matt Gallagher    15 年前

    总是使用 -Werror GCC设置 GCC_TREAT_WARNINGS_AS_ERRORS = YES )您的代码中不应该有警告,这是一个警告是严重错误的示例。

    另外,如果你得到 objc_exception_throw ,切换到控制台(command-shift-r)并查找第一个“低”号地址。

    2009-04-01 13:25:43.385 CrashExample[41720:20b] Stack: (
        2528013804,
        2478503148,
        2528036920,
        2528053460,
        2358032430,
        11076,
        11880,
        816174880,
        345098340,
        145973440,
        816174880,
    )
    

    在这种情况下,它将是“11076”。所以在控制台中键入:

    info line *11076
    

    这将告诉您代码中抛出异常的行。

        3
  •  8
  •   drewh    15 年前

    拼写错误的参数通常会导致在相关行中出现黄色的“警告:此类对象和此类对象不响应选择器X”。我相信这在默认情况下是打开的,因为我不需要更改任何编译器设置来查看这些设置。

    此外,当我遇到未捕获的异常时,有时可以将其放入gdb控制台(在执行应用程序时应该出现),然后键入以下内容以获取所有线程的回溯:

    英国电信公司

        4
  •  2
  •   Chris Lundie    15 年前

    您所做的并不是编译时错误,因为Objective-C运行时在运行时检查对象是否可以响应您发送给它的消息。

    我建议将此生成设置添加到目标或项目中:

    GCC_TREAT_WARNINGS_AS_ERRORS = YES
    
        5
  •  1
  •   Kendall Helmstetter Gelner    15 年前

    它不是编译错误的原因是,将编译时未知的消息发送到任何对象(并且可以将任何对象配置为动态处理消息)是完全有效的。所有方法调用实际上都是发送给对象的消息。

    一般来说,如果您看到任何警告,您应该解决它们,因为在大多数情况下,它们可能会导致问题(如您所见)。这里误导性的方面是,如果编译一个文件一次,而它只有警告,那么如果编译其他类而不更改有警告的类,那么警告将不会显示在编译器消息中。所以偶尔你可能会想“清理所有目标”,然后重新构建,以确保你没有错过任何警告。