zoukankan      html  css  js  c++  java
  • 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/
  • 相关阅读:
    hdu 5001(概率DP)
    hdu 5505(数论-gcd的应用)
    csu 1749: Soldiers ' Training(贪心)
    Button Bashing(搜索)
    Jury Jeopardy(反向模拟)
    interesting Integers(数学暴力||数论扩展欧几里得)
    湖南省第六届省赛题 Biggest Number (dfs+bfs,好题)
    csu 1551(线段树+DP)
    csu 1555(线段树经典插队模型-根据逆序数还原序列)
    csu 1552(米勒拉宾素数测试+二分图匹配)
  • 原文地址:https://www.cnblogs.com/zsw-1993/p/4879368.html
Copyright © 2011-2022 走看看