bug起源
最近在做解析二进制文件的工作,我的做法是写一个继承自ifstream的类然后封装一些函数以便于读取,譬如readUint32(), readHexString()等等。然后发现一个很隐蔽的bug........
bug简述
在读取一个数据时,该数据以00H结尾,我调用自己的函数返回一个string,请看下面简化的代码段:
include <iostream>
include <string>
using namespace std;
int main()
{
string str{ "test.aaa..ddd.bbb" };
str.push_back(0x00);
cout << str <<endl;
}
此时的输出会是什么呢?
image.png
加和不加没区别?非也!你去掉代码里的 endl就会发现尾部还有一个“空格”。于是乎,
if (str == "test.aaa..ddd.bbb")
>_<;
是不会被执行的。。
不止如此
00H这个字符的特殊性在于, 它会使 如下代码
if (str == "test.aaa..ddd.bbb ") // 多一个空格
_;
if (str == "test.aaa..ddd.bbb\0")
(;
// 以及
if (str + " " == "test.aaa..ddd.bbb")
QAQ;
同样不被执行。
原因
上面提到“空格”一词时,加上了引号,因为它并非我们常说的空格。ascii码表里00H 和32H的字符形式都是空白,而32H则是我们键盘上敲空格键敲出来的。即,执行如下代码:
cout << (int)(' ');
则得到 32。
最后一个疑惑是,ascii码表上 00H也可以用转义字符代替,那为何
str == "test.aaa..ddd.bbb\0"
的值是0,然而,如下代码段
string str{ "test.aaa..ddd.bbb" };
string yastr{ str };
str.push_back(0x00);
yastr.push_back('\0');
却会使 yastr 和str相等呢?
yastr == str ----> 1
我的实验环境是vs2015,这样的结果可能是取决于编译器(string == 操作的实现),也可能是c++认为字符字面量后面加\0没有实际的意义,后者是比较显然的。
总体来说今天的bug之旅以及反思都是愉快的。虽然有收获……但是……下次别再让我碰到你!
网友评论