不稳定的csb
昨天帮春哥看了个奇怪的问题: UI工程在没有发生修改的情况下,输出的二进制csb文件发生了变化。先用之前写的csb2json工具处理了下变化前后的csb,发现dump出来的数据是一模一样的。
这块逻辑最早来自cocos2dx, csb本质其实是flatbuffers序列化。
春哥说最近确实有更新导出工具,但只是fbs里新增加了一个类型,老工程不该受到影响才对。
直球分析
既然没有头绪就大力出奇迹,直接分析下数据内容;可以看到区别其实是children
和customClassName
对应数据位置颠倒了下。
table NodeTree |
翻下对应代码,看起来很像mBuilder.CreateVector(children)
和mBuilder.CreateString(customClassName)
执行顺序颠倒了。
return CreateNodeTree(mBuilder, |
这时候突然想到一个问题——好像编译器本来就不保证这种情况的执行顺序来着… 翻了下order of evaluation,确实是这样子来着。
验证猜想
接下来要想办法验证一下,所以我本地也编译了一个exe跑了下对比…结果发现不同的地方更多了orz
不过一样的思路,看了下其实就是另一个table
中元素顺序颠倒, 对应的代码为
auto csparsebinary = CreateCSParseBinary(mBuilder, |
改成明确调用顺序的版本后可以验证: 上面这个版本生成的csb和我刚才生成的一样,下面这个版本生成的csb和春哥生成的csb一样;。
区别其实就是test4
和test5
两行倒一下。
auto test5 = mBuilder.CreateString(animationName); |
auto test4 = mBuilder.CreateVector(animationInfos); |
索性找春哥要了下他生成的exe比了下,确实在没有手动声明的情况下、函数调用顺序是不一样的:
修复办法
确定原因之后,修复的思路就非常清晰了: 全部改成手动调用从而明确mBuilder.Create***
的调用顺序。
我后来翻了下官方示例写法,确实是一路手动声明下来; 换言之来自cocos2d-x的祖传实现用到现在其实是一直有风险的emmm
BTW: 我一开始怀疑是不同msvc版本下有区别,后来发现本地在debug和release下都有不少区别… 不过既然是合法行为、也懒得纠结了