一个回车引发的Bug

  前两天解决一个cocos2d-x 解析XML出错的Bug(链接在此),满有意思,记录下来。

迷雾重重

  问题是这样的:有引擎的用户在论坛上发帖说引擎在Windows7上跑一个需要从xml格式的游戏数据的测试例时程序会crash掉。

  看到这个问题很是疑惑,这个测试例我们发布版本前测试过多次了呀,在Windows上跑,在Mac上跑,在PC上跑,在手机上跑,在Iphone上跑,在Andorid上跑的都好好的,还会有什么问题呢?

山穷水尽

  不猜了,还是Debug先,嗯,公司开发环境只有WindowsXP,没有Windows7,既然都是Windows,那就在XP上跑跑先。Checkout代码…编译…运行…跑测试例…一切正常……

  晚上,正好本本是Windows7,再来…Checkout代码…编译…运行…跑测试例…挂了。哈哈,能重现就好,开始Debug,调呀调、调呀调,嗯?libxml2解析失败了?难道Windows7上Checkout出来的XML文件和别人的不一样了?用VC打开XML文件,VIM打开XML文件,调试,打开变量调试窗口、打开内存监视窗口,我左看右看上看下看它每个字母都一个样。

  到底是怎么回事呢?

柳暗花明

  按道理libxml2这么流行的解析库不应该有问题呀,翻翻代码:

   1: ......
   2: FILE * fp = fopen(pFilePath, "r");                                  // 打开文件
   3: fseek(fp,0,SEEK_END);                                               // 到文件尾
   4: unsigned nSize = ftell(fp);                                         // 获取文件长度
   5: fseek(fp,0,SEEK_SET);                                               // 返回文件头
   6: unsigned char *pBuffer = new unsigned char[nSize];                  // 分配数据缓存
   7: fread(pBuffer,sizeof(unsigned char), nSize,fp);                     // 读取文件内容
   8: ......
   9: xmlSAXUserParseMemory(&saxHandler, this, pBuffer, nSize);           // 解析文件内容
  10: ......                                                              // 有没有发现问题?

  貌似没什么问题?不管了,继续调试…下载libxml2的源码…编译Debug版本…替换工程中的库…单步调试解析XML文件数据…从解析第一句跟踪到最后一句…没问题呀…慢!都

数据解析完了,怎么还要继续读缓存中的数据?数据解析完了还继续访问,不挂掉才怪。

  在VC IDE的变量监视窗口中输入变量名(pBuffer, 1117)细细观察(顺便说一句1117是ftell返回的文件字节数)…终于发现问题了:

ftell返回的XML文件的字节数是1117,但pBuffer中到第9百多字符处已经是文件内容的结尾了,后面都是分配出来后未赋过值的内存,数据都是不确定的值,libxml2解析到后面怪不得会失败。

迟来的结论

  为什么ftell返回1117个字节,而fread只读取了9百多个字符呢?用VIM打开XML文件,转换为16进制仔细察看,终于发现了问题:问题出在回车上。嗯,用调试的例子解释太麻烦了,换个简单的说法:

  比如有一个文本文件,里面存着字符串"abcde\n12345”11个字符(不算那个结尾0),在内存中占用11个字节,我们把它放到文本文件中,这个文本文件的数据有多少字节呢?

  11和字节或者12个字节都有可能,因为在文件中回车可能是 "\n”(Linux)、"\r”(Mac)或者"\n\r”(Windows)。当fread在Windows上用"rt”模式读取文本文件时,它会自动把"\n\r”转换为"\n”。

  所以,按上面的代码逻辑:根据ftell返回的文件长度,分配了12个字节的缓存,fread读取整个文件数据,填充了前11个字节,交给libxml2解析的数据为"abcde\n12345?”(?为未赋值的内存),当解析到?处发生了解析失败。找到原因了,解决问题就简单了:

   1: nSize = fread(pBuffer, sizeof(unsigned char), nSize, fp);

  编译…运行测试例…通过…收工。

 

 

疑惑为什么在WindowsXP上运行就没问题呢?

转载于:https://www.cnblogs.com/yangws/archive/2011/03/13/1983033.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值