最近在做cocos2dx的自更新,因为一开始没有选择用lua,所以现在不得不找其他出路来做自更新。
当然直接的想法就是把逻辑丢到一个动态库里面,框架部分加一个资源管理ok。然后问题就来了
一开始在4.4的android设备上测试,一切正常,但是拿到4.0.4的机器上就直接崩溃了,anrdoid调试起来很困难,弄了很久也没搞定,放弃。
第一个症状,初始化LabelAtlas时挂掉,挂的很尴尬,看不出理由的(至少当时是这样),看着好像内存被写乱了,但是怎么也查不到。
然后瞎折腾了半天,居然找到了一个解决方法。因为是在LabelAtlas写本地字符缓冲m_sString时导致的崩溃,弄了很多方法,最后在UICCLabelAtlas加了一个函数修改m_sString,在setProperty之前调用这个函数先写入传来的字符串。崩溃没了(原因至今不明)。
然后继续玩下
二号问题来了。登陆部分做了账号密码缓存,这个东西用到了CCUserDefault,实际上这个东西在win32下跟android上的实现完全不同。结果是,如果玩家第一次进入,也就是没有账号密码缓存的时候,返回的数据一旦被操作就会导致内存错误,产生段错误而崩溃。这个问题也仅存在于4.0.4的设备上(其他低版本设备没测试过)。
最后说重点,问题产生的原因,与解决方法。
原因是就是标题说的,stl对象跨动态库传递导致。stl全都是基于模板的,模板是在编译器生成的。这也就是说同一份stl代码在不同动态库中有各自的实现,如果只是方法多了一份自然就没问题,但是部分stl容器里面存有一些静态变量,因此多个实现会导致多份静态变量,然后导致某些方法的调用出现差别,最终导致内存操作异常而崩溃(这个原因是网上查的,这些是我大概的理解原链接)。
LabelAtlas里面有一个UICCLabelAtlas对象。而UICCLabelAtlas继承自CCAtlasNode,CCAtlasNode则是cocos2dx库中的东西,cocos2dx被我编译成了一个独立的so文件,LabelAtlas则在libextension.so中。m_sString成员变量是在CCAtlasNode中定义的,因此UICCLabelAtlas的存在导致了m_sString被两个so中的stl实现所操作,然后崩溃。
CCUserDefault是cocos2dx的实现,我的逻辑代码则在逻辑动态库中,而取值函数getStringForKey的返回参数则是一个std::string,同样造成了一个对象被两套方法处理导致混乱崩溃。
PS:cocos2dx版本2.2.2,这种问题在win32,android4.2+,ios模拟器7.0+都没有出现过,另外第一个问题的奇怪解法也让我看不懂,有知情者请留言交流