8

我正在调试一个严重 assert() 的 iPhone 应用程序(Xcode、Objective-C++ 和设备模拟器)。在某些情况下,断言失败只会终止应用程序,而不是像我期望的那样闯入调试器。

我通过实施我自己的有点断言来解决:

#define AssertLite(b) if(!(b)) {asm {int 3}}

(绒毛省略),但我想知道是否有人遇到过这种情况。我无法确定它何时中断以及何时终止的模式。代码没有线程化;它所做的一切都是在事件处理程序中完成的。

为什么会发生这种情况,我如何让 vanilla assert() 表现得像一个条件断点?

4

4 回答 4

15

First off, since you are working on an iPhone app, you should probably use NSAssert() instead of the vanilla BSD assert function.

e.g. NSAssert(the_object, @"NIL object encountered");

The NSAssert macro will throw an Objective-C exception (NSInternalInconsistencyException) if the assertion fails.

Since your goal is to break on the exception, the next step is to make the Xcode debugger break on Objective-C exceptions. This is probably a good thing to do anyway.

In the Breakpoints window (Run->Show->Breakpoints menu item), click where it says "Double-Click for Symbol" to enter the symbol -[NSException raise]

The last thing to be careful off is that NSAsserts do not compile out in a release build. That means that you have to either be prepared to handle the exception in your application, or you need to create your own macro that does compile out in release builds.

Here's the macro I use to compile out assertions in runtime code (note that I then use HMAssert in my code instead of NSAssert):

#ifdef DEBUG
#   define HMAssert(A,B) NSAssert(A,B)
#else
#   define HMAssert(A,B)
#endif

This requires a DEBUG preprocessor macro to be defined. Here's how to set that up:

  1. Right-click on your project in Xcode. That will be the top item in the left panel where your projects files are listed
  2. Select "Get Info" from the context menu that pops up.
  3. Go to the "Build" tab.
  4. Make sure the "Configuration" is set to "Debug".
  5. Type DEBUG into the field next to "Preprocessor Macros" under "GCC 4.2 - Preprocessing".
于 2010-01-05T00:48:52.493 回答
4

首先,如果您在断点导航器 (⌘6) 中“添加异常断点...”,调试器将在 NSAssert 失败时停止,让您查看堆栈并了解哪里出了问题。

您应该使用标准的 NSAssert。如果您正确使用它,您不需要手动创建很多东西——Mike 提到的所有内容都类似于默认的 NSAssert 实现。

您应该在预编译的头文件中设置 NS_BLOCK_ASSERTIONS 来运行发布配置(按照 Mike 的步骤),以禁用断言。如果您需要有关为什么这样做的更多信息,请查看: http: //myok12.wordpress.com/2010/10/10/to-use-or-not-to-use-assertions/

于 2010-11-24T02:52:09.613 回答
0

有一次,我看到一次与 assert() 调用不同的行为。这是由编译器在构建过程的不同部分选择不同的宏定义引起的。

一旦包含路径被理顺,它们的工作方式都是一样的。

于 2013-02-14T07:57:27.193 回答
0

在 Xcode 4 和新的 iOS 中,NSAssert 实际上可能采用一个可变参数列表。这对于将一些值与断言一起记录可能很有用。编译断言(见上面 Mike 的回答)可以这样定义:

#ifdef DEBUG
#   define DAssert(A, B, ...) NSAssert(A, B, ##__VA_ARGS__);
#else
#   define DAssert(...);
#endif

此外,不再有 Run → Show → Breakpoints 菜单项。请参阅这篇文章以设置 Xcode 4 以中断如上定义的断言。

于 2012-04-23T13:50:39.617 回答