zoukankan      html  css  js  c++  java
  • 使用_snscanf_s转换十六进制时引起的内存越界

    //将Hex编码转换为指定编码格式的字符串
    string Encoding::DecodeHexString(const string &strSrc, UINT code_page )
    {
        string::size_type length = strSrc.length() / 2;
        char *result = new char[length + 1];
        ZeroMemory(result, length + 1);
        const char* str = strSrc.c_str();
        for(string::size_type i = 0; i < length; ++i)
        {
            _snscanf_s(str + (i * 2), 2, "%X", &result[i]);
        }
    
        string str = ConvertTo((char*)result, code_page);
        delete[] result;
    
        return str;
    }

      此函数中,传入strtSrc参数是一个经过十六进制编码的字符串,此函数将每两个十六进制字符转换成一个十进制数,然后再转换未指定编码格式的字符串。

      从逻辑上看,这段代码没什么问题。但是程序运行到delete[] result;语句时就会出错,无法删除数组。

      因为经验不足,当时怎么想都没想明白。花了好几个小时调试才发现问题所在。

      _snscanf_s每次都往result写入4个字节(int),而result每个元素都是1字节,这就相当于一次写入了4个char。我的原意是每次输入一个1字节的十进制数。

      这就导致最后数组长度增加了3个字节,也就是发生了内存越界。delete操作也就出错了。

      修改后正确的代码应该是这样:

    //将Hex编码转换为指定编码格式的字符串
    string Encoding::DecodeHexString(const string &strSrc, UINT code_page )
    {
        string::size_type length = strSrc.length() / 2;
        char *result = new char[length + 1];
        ZeroMemory(result, length + 1);
        const char* str = strSrc.c_str();
        int value = 0;
        
        for(string::size_type i = 0; i < length; ++i)
        {
            _snscanf_s(str + (i * 2), 2, "%X", &value);
            result[i] = value;
        }
    
        string str= ConvertTo((char*)result, code_page);
        delete[] result;
    
        return str;
    }

      用一个4字节的int类型变量来接收输出参数,再赋值给result数组就可以了。int赋值给char这样做不就会发生截断吗?那么数据不就失真了么?

      是的,这样做会发生截断,但是不会失真。

      因为将字节流Hex编码的字符串时,每一个字节表示的数都会转换为unsigned char(1字节), 所以解码Hex字符串时所得到的数不可能超过255(1字节)。

  • 相关阅读:
    12个Web开发者应该掌握的Firebug技巧
    sql语句修改表结构
    从数据库中查询数据
    收发短信API
    日志12.03
    监听短信数据库变化
    漫谈C语言及如何学习C语言(转)
    阅读短信
    在src文件中寻找短信数据库表
    拦截短信示例1
  • 原文地址:https://www.cnblogs.com/dvwei/p/3543041.html
Copyright © 2011-2022 走看看