10

我是一名长期的 Microsoft 开发人员,而且我是使用 Xcode 进行 iPhone 开发的新手。因此,我正在阅读一本书并通过示例尝试自学如何使用 Objective-C 编写 iPhone 应用程序。到目前为止一切都很好,但是,有时我会objc_exception_throw在运行时遇到通用的“ ”消息。发生这种情况时,很难找到此异常的来源。经过反复试验,我找到了答案。其中一个参数拼写错误。

正如您在下面看到的,我通过省略按钮中的第二个“t”拼错了“otherButtonTitles”参数。

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

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

4

5 回答 5

25

首先,打开~/.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 SDKDevice - iPhone OS [someversion]. 一直滚动到底部并找到该GCC 4.0 - Warnings部分。那里; 尽可能多地打开警告,但请确保打开Treat Warnings as Errors(这相当于GCC_TREAT_WARNINGS_AS_ERRORS)。就个人而言,我将其设置为:

GCC 警告构建设置
(来源:lyndir.com

您现在应该会收到编译器警告,因为您可以在代码中做错大多数事情,并且编译器不会让您运行代码,直到您修复它们。当事情确实超出了编译器的范围时,您应该能够在方便的地方通过 GDB 中断轻松找到问题。

您还应该调查NSZombie*. 这些是环境变量,对于早期破坏内存分配或访问错误的情况非常方便。例如; 什么NSZombieEnabled都不会真正被释放;在 dealloc 上,它会被覆盖,_NSZombie如果你尝试再次访问这个释放的内存(解除对释放指针的引用),你会在 GDB 中得到一些中断,而不是像往常一样通过调用,只在随机数据上发出(当然,这不是您想要的)。有关这方面的更多信息,请参阅http://www.cocoadev.com/index.pl?NSZombieEnabled

于 2009-04-03T05:38:30.013 回答
9

始终使用-WerrorGCC 设置 ( 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

这将告诉您代码中引发异常的行。

于 2009-04-02T23:30:00.927 回答
8

拼写错误的参数通常会在相关行以黄色显示“警告:某某对象不响应选择器 x”。我相信默认情况下这是打开的,因为我不必更改任何编译器设置即可看到这些。

此外,当我遇到未捕获的异常时,有时进入 gdb 控制台(应该在您执行应用程序时出现)并键入以下内容以获取所有线程的回溯是有益的:

呸呸呸呸

于 2009-04-02T21:17:02.340 回答
2

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

我建议将此构建设置添加到您的目标或项目中:

GCC_TREAT_WARNINGS_AS_ERRORS = YES
于 2009-04-02T22:14:07.647 回答
1

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

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

于 2009-04-02T21:31:35.847 回答