zoukankan      html  css  js  c++  java
  • CCFileUtils::getFileData疑惑

    背景

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

    项目结构

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

     

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

     

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

     

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

    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的团队为什么不修改一下。

  • 相关阅读:
    第三方驱动备份与还原
    Greenplum 解决 gpstop -u 指令报错
    yum安装(卸载)本地rpm包的方法(卸载本地安装的greenplum 5.19.rpm)
    Java JUC(java.util.concurrent工具包)
    netty 详解(八)基于 Netty 模拟实现 RPC
    netty 详解(七)netty 自定义协议解决 TCP 粘包和拆包
    netty 详解(六)netty 自定义编码解码器
    netty 详解(五)netty 使用 protobuf 序列化
    netty 详解(四)netty 开发 WebSocket 长连接程序
    netty 详解(三)netty 心跳检测机制案例
  • 原文地址:https://www.cnblogs.com/zzrom/p/3899052.html
Copyright © 2011-2022 走看看