xcode 为什么断言只是终止为 iPhone 编译的程序?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2000977/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does assert simply terminate a program compiled for iPhone?
提问by Seva Alekseyev
I'm debugging a heavily assert()'ed iPhone app (Xcode, Objective-C++, and device simulator). In some cases, the assert failure would just terminate the app, instead of breaking into the debugger as I'd expect.
我正在调试一个大量使用 assert() 的 iPhone 应用程序(Xcode、Objective-C++ 和设备模拟器)。在某些情况下,断言失败只会终止应用程序,而不是像我期望的那样闯入调试器。
I made a workaround by implementing my own kinda-assert to the effect of:
我通过实现我自己的某种断言来解决以下问题:
#define AssertLite(b) if(!(b)) {asm {int 3}}
(fluff omitted), but I wonder if anyone ever encountered this. I could not determine a pattern as to when does it break and when does it terminate. The code is not threaded; all it does is done in event handlers.
(省略了绒毛),但我想知道是否有人遇到过这种情况。我无法确定何时中断以及何时终止的模式。代码没有线程化;它所做的一切都是在事件处理程序中完成的。
Why does this happen and how do I make vanilla assert() behave like a conditional breakpoint it should be?
为什么会发生这种情况,我如何让 vanilla assert() 表现得像条件断点一样?
回答by Michael Taylor
First off, since you are working on an iPhone app, you should probably use NSAssert() instead of the vanilla BSD assert function.
首先,由于您正在开发 iPhone 应用程序,您可能应该使用 NSAssert() 而不是普通的 BSD 断言函数。
e.g. NSAssert(the_object, @"NIL object encountered");
例如 NSAssert(the_object, @"NIL object encountered");
The NSAssert macro will throw an Objective-C exception (NSInternalInconsistencyException
) if the assertion fails.
NSInternalInconsistencyException
如果断言失败,NSAssert 宏将抛出一个 Objective-C 异常 ( )。
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.
由于您的目标是中断异常,下一步是使 Xcode 调试器中断 Objective-C 异常。无论如何,这可能是一件好事。
In the Breakpoints window (Run->Show->Breakpoints menu item), click where it says "Double-Click for Symbol" to enter the symbol -[NSException raise]
在 Breakpoints 窗口(Run->Show->Breakpoints 菜单项)中,单击“Double-Click for Symbol”以输入符号 -[NSException raise]
The last thing to be careful off is that NSAsserts do notcompile 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.
最后要注意的是 NSAsserts不会在发布版本中编译出来。这意味着您必须准备好处理应用程序中的异常,或者您需要创建自己的宏,以便在发布版本中编译出来。
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):
这是我用来在运行时代码中编译断言的宏(请注意,我然后在我的代码中使用了 HMAssert 而不是 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:
这需要定义一个 DEBUG 预处理器宏。以下是设置方法:
- Right-click on your project in Xcode. That will be the top item in the left panel where your projects files are listed
- Select "Get Info" from the context menu that pops up.
- Go to the "Build" tab.
- Make sure the "Configuration" is set to "Debug".
- Type DEBUG into the field next to "Preprocessor Macros" under "GCC 4.2 - Preprocessing".
- 在 Xcode 中右键单击您的项目。这将是左侧面板中列出您的项目文件的顶部项目
- 从弹出的上下文菜单中选择“获取信息”。
- 转到“构建”选项卡。
- 确保“配置”设置为“调试”。
- 在“GCC 4.2 - 预处理”下“预处理器宏”旁边的字段中键入 DEBUG。
回答by Ohad Kravchick
First of all, if you "Add Exception Breakpoint..." in the Breakpoint Navigator (?6), the debugger will stop on NSAssert's failures, allowing you to look at the stack and understand what went wrong.
首先,如果您在 Breakpoint Navigator (?6) 中“Add Exception Breakpoint...”,调试器将在 NSAssert 失败时停止,让您查看堆栈并了解出了什么问题。
You should use the standard NSAssert. If you use it correctly, there is not a lot that you need to manually create -- everything Mike mention is similar to the default NSAssert implementation.
您应该使用标准的 NSAssert。如果您正确使用它,则不需要手动创建很多东西——Mike 提到的所有内容都类似于默认的 NSAssert 实现。
You should run you release configuration with NS_BLOCK_ASSERTIONS set in your precompiled headers (follow Mike's steps), to disable assertions. If you need more info on why to do so, check out: http://myok12.wordpress.com/2010/10/10/to-use-or-not-to-use-assertions/
您应该在预编译头文件中设置 NS_BLOCK_ASSERTIONS 来运行发布配置(按照 Mike 的步骤),以禁用断言。如果您需要更多关于为什么这样做的信息,请查看:http: //myok12.wordpress.com/2010/10/10/to-use-or-not-to-use-assertions/
回答by Greg
In Xcode 4 and new iOS, NSAssert may actually take a variable list of parameters. This may be useful to log some values together with the assert. The compiling-out assert (see answer by Mike above) could be defined like this:
在 Xcode 4 和新的 iOS 中,NSAssert 实际上可能采用一个可变的参数列表。这对于将某些值与断言一起记录可能很有用。编译断言(见上面 Mike 的回答)可以这样定义:
#ifdef DEBUG
# define DAssert(A, B, ...) NSAssert(A, B, ##__VA_ARGS__);
#else
# define DAssert(...);
#endif
Also, there is no longer Run → Show → Breakpoints menu item. See this postto set up Xcode 4 to break on an assert as defined above.
此外,不再有运行 → 显示 → 断点菜单项。请参阅此帖子以设置 Xcode 4 以中断上述定义的断言。
回答by Walt Sellers
One time I saw a different behavior from the assert() calls once. It was caused by the compiler picking up different macro definitions at different portions of the build process.
有一次,我看到了一次与 assert() 调用不同的行为。这是由于编译器在构建过程的不同部分选择了不同的宏定义造成的。
Once the include paths were straightened out, they all worked the same.
一旦包含路径被理顺,它们的工作方式都是一样的。