const

本文就记录一下最近的一个bug以及解决步骤。这个问题主要是由于const引起,导致第三方库WXOpenIMSDK奔溃。
背景
最近在优化项目中的蓝牙打印,原本的蓝牙打印速度实在是不敢恭维哈,按测试的话说:"听着打印声音,等打印等的快睡着了",好吧这个是不能忍,只能优化了不然怎么对得起那几百万的用户量,虽然使用蓝牙打印的用户量只有几十万,蓝牙打印的优化暂时没有时间去整理出文章,这边就先提一下后续会整理。在封装蓝牙打印的类中使用了常量定义一下属性,方便后续调整参数,如下:

const CGFloat compress= 0.1f;

而在第三库中也有相同的定义,但是我们是不知道的,是属于未开源的代码中,报错如下:

const
文章图片
报错&线程.png
打印了下全部的线程,如下:
(lldb) bt **** was compiled with optimization - stepping may behave oddly; variables may not be available. * thread #41, stop reason = EXC_BAD_INSTRUCTION (code=1, subcode=0xa0000000) frame #0: 0x0000000103e8d3f8 ****`compress * frame #1: 0x00000001038bdeb8 ****`::compressData() at TcmPackData.h:106 [opt] frame #2: 0x00000001038bdb34 ****`::addSccommHeader() at SccomHelper.cpp:35 [opt] frame #3: 0x00000001038c9704 ****`INetImpl::RegisterFd(int, int) [inlined] std::tr1::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count >(this=, __p=) at boost_shared_ptr.h:273 [opt] frame #4: 0x00000001038c00c0 ****`::syncCall() at TcmInet.cpp:2210 [opt] frame #5: 0x00000001038bf638 ****`::exchangeKey() at TcmInet.cpp:298 [opt] frame #6: 0x00000001038c0ce8 ****`::LoginToServer() at TcmInet.cpp:983 [opt] frame #7: 0x00000001038c307c ****`::loginThreadFunc() [inlined] LoginAuthPw at TcmInet.cpp:1054 [opt] frame #8: 0x00000001038c3068 ****`::loginThreadFunc() [inlined] Login at TcmInet.cpp:1120 [opt] frame #9: 0x00000001038c3044 ****`::loginThreadFunc() at TcmInet.cpp:1218 [opt] frame #10: 0x0000000180b2d75c libsystem_pthread.dylib`_pthread_body + 240 frame #11: 0x0000000180b2d66c libsystem_pthread.dylib`_pthread_start + 284 frame #12: 0x0000000180b2ad84 libsystem_pthread.dylib`thread_start + 4

通过以上内容最后是锁定了第三方库WXOpenIMSDK,为了不妨碍其他人员开发只好先把调用第三方库的方法给注释掉,接下来是各种爬坑之旅。
由于更新了其它一些第三方库(现在挺多第三方库内引用了相同的库容易出问题)以及Xcode 10正式版本发布,去更新了Xcode 也就增加了排查的难度,说多了都是血...
爬坑——依赖库?
由于更新了一些库是有可能是由于依赖库的排序问题导致的,毕竟有些是需要让依赖库的先后顺序加载才能正常初始化,只好去拉取旧版本的代码然后一一对比,矫正排序,然后还是崩溃,只能换个方式继续了。
接着爬——SDK?
既然不是依赖库的问题,那会不会是第三方库SDK的问题,只好去pod update一波,还是崩溃。?又把Pod更新的库倒回防止增加排查力度...
再爬——Xcode?
是不是Xcode的问题啊...毕竟这家伙没少坑人,去更新Xcode,然后发现人更疯了,Xcode 10需要调整以及缺少了一些C++依赖库的问题...当然结果还是徒劳的该崩溃还是接着崩溃。顺带附上Xcode 10调整方法,既然适配好了Xcode 10总不能再倒回去吧,毕竟都是崩溃,只能接着往下爬坑了。
没辙了——对比文件
使用Beyond Compare工具,需要的可以自行百度搜索下载哈。文件对比,最好的是两份相近的文件或者源码,但是辣么多小伙伴一直在开发更新Git这个就痛苦了,毕竟检出提交记录需要花一大堆的时间去编译,还有那么多需要对比的提交记录内心是崩溃的,通过半天的时间锁定了最近一段时间内的一些提交记录,又在花了半天的时间锁定了两份相隔就一个提交记录的源码。通过工具Beyond Compare一一对比,就发现一些.m源码的差异,还是没找到问题。最后大胆的猜想是不是Const的问题,尝试着修改常量,发现解决了...心里一万头草泥马狂奔而过。人生本来就这么艰难了,连个const都要来凑热闹下个毒...
复习Const
const在一些情况下与宏定义有点类似,但是两者之间还是有区别的。
宏定义 宏定义属于预编译指令,在程序运行之前已经编译好了的,并且每一个宏定义都会在内存中临时开辟一份内存空间。
const 由于被const修饰,常量是无法被修改的,并且const修饰的常量只被初始化一次,只开辟一块内存空间。
UIKIT_EXTERN 一般常量的用法:
.h UIKIT_EXTERN NSString *const kUserName; .m NSString *const kUserName = @“daver”

在其他类里面可以被调用,类似于宏定义,尽量使用常量定义来代替宏定义,毕竟修改宏定义后需要重新编译(由于项目比较大编译时间太长,尽量能不重新编译就不重新编译),当然在开辟内存上也是有区别的。
只用于.m中 【const】由于单纯的在.m中定义会导致其他地方没法调用,但是是存在的,而会出现以上的问题(通过本bug可以推测出的),针对以上问题做了两条建议:
  • 常量名尽量长一些,防止与其他地方冲突
  • 如果是只在某个类内使用,请加上static防止被外部使用,如下:
static const CGFloat kPrinterCompress= 0.1f; // 或者 static CGFloat const kPrinterCompress= 0.1f;

总结
好吧,总算是解决了,也发个帖子共享下万马崩腾的内心...

    推荐阅读