assert出问题了?

刚学习Objective-C那会儿,还不太了解这个世界的惯用法,所以有些地方使用了C/C++的方式,虽然后来做过一定的修改, 但是项目中还是遗留了一些无关紧要的C/C++代码。比如对断言的运用。

assert(some != nil); 

问题

使用assert倒是没遇到啥问题,不过有一次在查阅测试同学提交上来的crashlog, 发现竟然崩在了assert调用上。

Thread 0 Crashed:
0   libsystem_kernel.dylib        0x3aaf61fc __pthread_kill + 8
1   libsystem_pthread.dylib       0x3ab5fa2e pthread_kill + 54
2   libsystem_c.dylib             0x3aaa6ff8 abort + 72
3   libsystem_c.dylib             0x3aa86d22 __assert_rtn + 178
4   test                          0x000f8b36 -[AppDelegate application:didFinishLaunchingWithOptions:]
......
15  CoreFoundation                0x300c014a __CFRunLoopRun + 1394
16  CoreFoundation                0x3002ac22 CFRunLoopRunSpecific + 518
17  CoreFoundation                0x3002aa06 CFRunLoopRunInMode + 102
18  UIKit                         0x328d2dd4 -[UIApplication _run] + 756
19  UIKit                         0x328ce044 UIApplicationMain + 1132
20  test                          0x000f8bde main (main.m:16)
21  libdyld.dylib                 0x3aa3fab4 start + 0

还真是稀奇,这到底是怎么回事呢?


缘由

首先,assert不是应该只在NDEBUG没有定义的时候有效么?难道Release默认没有设置这个宏?

通过Xcode日志很容易就发现Release下果然没有设置NDEBUG,验证了前面的假设。

可是为什么Release下默认没有设置这个宏呢?我记得NDEBUG 是语言标准的一部分啊?

查阅文档, 结果如下。

也就是说, NDEBUG确实是语言的标准,但是标准只定义了它是怎么影响assert的, 并没有定义编译器应该在什么情况下定义NDEBUG,所以XcodeRelase模式下没有定义也是合乎标准的。


继续挖掘

问题找到原因了,可是我还是不死心,那如果Xcode是这样对待assert的, 那么自家的NSCAssert呢?

Foundation/NSException.h中,NSCAssert大致是这样的定义的:

#if !defined(NS_BLOCK_ASSERTIONS)
#define NSCAssert(condition, desc, ...) \
    do {               \
   __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \
   if (!(condition)) {     \
       [[NSAssertionHandler currentHandler] handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \
       file:[NSString stringWithUTF8String:__FILE__] \
           lineNumber:__LINE__ description:(desc), ##__VA_ARGS__]; \
   }               \
        __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \
    } while(0)
#else
#define NSCAssert(condition, desc, ...) do {} while (0)
#endif 

assertNDEBUG来控制类似, NSCAssert是由NS_BLOCK_ASSERTIONS控制的。

那么Release下的NSCAssert会不会也会触发程序崩溃呢?

通过查阅XcodeRelease模式下的构建日志,发现答案是不是的。


总结

我只能说Xcode这里做的略不厚道,既然你给自家的NSCAssert定义了开关,那么也应该关照到assert

作为开发人员,我们有两个处理办法。

  • 不用assert, 完全改成NSCAssert(注意不要使用NSAssert,详见这里)。但是要同时注意你使用的第三方代码。
  • 在工程设置Build Settings -> Preprocessor Macros -> Release中添加NDEBUG=1, 如下图。










from:http://imoldman.github.io/blog/2014/04/30/why-assert-enabled-under-release-in-xcode/
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值