背景

这几天在使用cocos2d-x读取磁盘文件的时候,发现了CCFileUtils中一点不合理的地方,特此记录,以供研讨。

项目结构

①我使用的是cocos2d-x 2.1.3版本,CCFileUtils::getFileData的函数签名为:

但据观测,即使是最新版的cocos2d-x 3.2,这部分声明和实现仍没有变化。

②我们假设在项目Resources目录下,有data.txt,其中内容大致为下图:

③下面以win32和android两种平台做对比来分析其中出现的问题。

Win32

①读取文件的代码

②实际执行的读取代码

文件路径:cocos2dx\platform\CCFileUtils.cpp

③过程分析

在Windows中,行结尾符是”\r\n”,所以当程序执行完381行时,

*pSize = ( 5+2+6+2+6 , 21 );

当程序执行完384行时,

*pSize = ( 5+1+6+1+6 , 19 );

当程序返回时,

*pSize == 19; //没有问题

sizeof(pBuffer) == 21; //没有问题

pBuffer == “apple\norange\nbananba?????”; //问题很严重

④结果

当执行步骤①的代码时,我们使得data指向了这样一个字符串:

1.一段以”r”模式读取文件的代码,却在其中包含了’\n’;

2.这个字符串没有’\0’结尾。

这里的问题很好解决,只要我们添加下面一条语句,就可以避免悲剧:

data[pSize] = ‘\0’;

Windows平台上的问题很好解决,下面我们转向android.

Android

①读取文件的代码

②实际执行的读取代码

文件路径:cocos2dx\platform\android\CCFileUtilsAndroid.cpp

③过程分析

由于Android平台上行结尾符为\r,所以当执行完415行时,

*pSize = ( 5+1+6+1+6 , 19 );

sizeof(pBuffer) == 19

有问题吗?很严重。

④结果

下面回到步骤①,此时的data指向了一个字符串,这个字符串:

1.一段以”r”模式读取文件的代码,却在其中包含了’\n’;

2.这个字符串没有’\0’结尾。

但是,此时我们不能使用win32平台的解决方案。

data[size] = ‘\0’; //数组越界!

data[size-1] = ‘\0’;//banana中的最后一个a会被删除

此时,在语言层面上,只有把这段内存复制到一个更安全的地方,才可以解决这种冲突。如果你直接操纵data,几乎可以肯定会出问题。

错误解法:string str = (char*)data;

正确解法:string str( data, data+size );

结论

CCFileUtils::getFileData,一旦你以”r”模式来使用它,data就会变成一个没有’\0’结尾的字符串;一旦你在一个行结尾符是由单个字节组成的系统中使用它,你就不能给它加一个’\0’。如果不注意这两点,几乎可以肯定会误用这个函数。所以使用它的时候,请谨慎!

并且,请使用string str( data, data+size );的形式来复制这个易错字符串。

PS

话说这个函数的声明和实现相当容易被误用,不仔细分析几乎一定会被误用,因为其中的一些做法完全是和常识相违背的,不知道cocos2d-x的团队为什么不修改一下。

CCFileUtils::getFileData疑惑的更多相关文章

  1. cocos2d::CCFileUtils::sharedFileUtils()->getFileData(szFile, "r", &bufferSize) 不同平台返回值不一样

    string pathKey = CCFileUtils::sharedFileUtils()->fullPathForFilename(fileName); unsigned char* pB ...

  2. 基于Quick-cocos2d-x的资源更新方案 二

    写在前面 又是12点半了,对于一个程序员来说,这是一个黄金时间,精力旺盛,我想,是最适合整理和分享一些思路的时候了. 自从上次写了 基于Quick-cocos2d-x的资源更新方案 同样可见quick ...

  3. cocos2dx游戏资源加密之XXTEA

    在手机游戏当中,游戏的资源加密保护是一件很重要的事情. 我花了两天的时间整理了自己在游戏当中的资源加密问题,实现了跨平台的资源流加密,这个都是巨人的肩膀之上的. 大概的思路是这样的,游戏资源通过XXT ...

  4. cocos2dx 不同平台上加载文件

    原文转自:http://blog.sina.com.cn/s/blog_62b2318d0101eozt.html cocos2dx在不同平台上读取资源文件时的处理方式是不同的. 在ios下,程序调用 ...

  5. 如何学习 cocos2d-x ?

    发表于 04/23/2014 作者 zrong — 24 条评论 ↓ 11,687 次查看 本站文章除注明转载外,均为本站原创或者翻译. 本站文章欢迎各种形式的转载,但请18岁以上的转载者注明文章出处 ...

  6. cocos2d-x lua 中使用protobuf并对http进行处理

    cocos2d-x lua 中使用protobuf并对http进行处理 本文介绍 cocos2d-x lua 中使用http 和 基于cocos2d-x 对lua http的封装(部分ok) 本博客链 ...

  7. Atitit 图像处理的心得与疑惑 attilax总结

    Atitit 图像处理的心得与疑惑 attilax总结 1.1. 使用类库好不好??还是自己实现算法1 1.2. 但是,如果遇到类库体积太大,后者没有合适的算法,那就只能自己开发算法了1 1.3. 如 ...

  8. 每日一记-mybatis碰到的疑惑:String类型可以传入多个参数吗

    碰到一个觉得很疑惑的问题,Mybatis的parameterType为String类型的时候,能够接收多个参数的吗? 背景 初学Mybatis的时候,看的教程和书籍上都是在说基本的数据类型如:int. ...

  9. 解决上一篇jquery中on的疑惑

    内容都是来自:http://www.365mini.com/page/jquery-on.htm.这里做一下收藏.文章的最后  疑问和解答可以解决所有的疑惑  看了之后能更好的整篇文章. on()函数 ...

随机推荐

  1. jQuery工作原理解析以及源代码示例

    jQuery的开篇声明里有一段非常重要的话:jQuery是为了改变javascript的编码方式而设计的.从这段话可以看出jQuery本身并不是UI组件库或其他的一般AJAX类库.jQuery改变ja ...

  2. HTML&CSS基础学习笔记1.2-HTML的全局属性?

    HTML元素都有属性,下面的这些全局属性是所有的HTML元素都可以使用的. 常见的有: HTML元素也有一些本身自己独特的属性,我们以后的笔记中有机会,会再为大家介绍哦. 下面是代码测验,具体的内容可 ...

  3. python比较两个列表

    两个列表,随机产生4个不相等的数,计算一下,相同位置上的元素相等的个数,用k1表示. b列表中的元素在a列表中,但位置不相同,有多少个,用k2表示. 例如: a=[0, 4, 7, 3]b=[7, 1 ...

  4. Repeater绑定数据库,使用AspNetPager进行分页

    分页是Web中经常遇到的功能,分页主要有真分页和假分页. 所谓真分页是指:每一页显示多少数据,就从数据库读多少数据: 假分页是指:一次性从数据库读取所有数据,然后再进行分页. 这两种分页方式区别在于从 ...

  5. JavaWeb学习笔记--3.JavaBean

    JavaBean 是一种JAVA语言写成的可重用组件.为写成JavaBean,类必须是具体的和公共的,并且具有无参数的构造器.JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性 ...

  6. Unity3D中的工具类

    1.时间:Unity提供了Time类,这个类主要用来获取当前的系统时间. Time.time:从游戏开始后开始计时,表示截止目前共运行的游戏时间. Time.deltaTime:获取Update()方 ...

  7. ultraedit删除空行(含空格,tab,制表符等怪字符)

    打开ultraedit,ctrl+r弹出替换对话框,点选启用正则表达式 在查找框输入 ^p^p 在替换框输入  ^p 仍有部分空行还在,继续处理: 查找框中输入:%[ ^t]++^p,注意^t之前有空 ...

  8. qt鼠标事件总结(坐标,跟踪,点击判断)

    1.QMouseEvent中的坐标QMouseEvent中保存了两个坐标,一个是全局坐标,当然另外一个是局部坐标.全局坐标(globalPos())即是桌面屏幕坐标(screen coordinate ...

  9. javascript笔记4之运算符

    /* var box = 100; --box; //前置递增,box = box +1 alert(box);//99 var box = 100; var age = ++box; //先box累 ...

  10. VSCode

    下载: 打开终端控制器 wget http://download.microsoft.com/download/0/D/5/0D57186C-834B-463A-AECB-BC55A8E466AE/V ...