使用_snscanf_s转换十六进制时引起的内存越界
2014-02-10 15:51 DVwei 阅读(910) 评论(0) 编辑 收藏 举报//将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字节)。