String赋值错误引发的一个Bug
- 某日在实现一个新功能时,在代码中很不起眼的一行,调用一个接口时将其一个为string类型的形参,赋值为0。
- 编译通过,然后程序每次调用新功能时必Crash。
- 之后,通过追加Log,反复查找。最终定位到传错参数类型的接口调用处。
// 错误示例
// some Code
if (NULL != obj) {
// id message callbackid(string类型)
// 第三个参数,为string,将其传入0
obj->func(0, "Linduo", 0)
}
// somd Code
原因分析
- 第一个,自然是敲代码时,不仔细。认为CallbackID是数字类型,有点想当然了。
- 对于String,赋值为int类型,一般来讲,编译是无法通过的。
std::string s = 3;
编译时会报错:conversion from ‘int’ to non-scalar type ‘std::__cxx11::string {aka std::__cxx11::basic_string}’ requested
- 但是对于数字0,这个东西比较特殊。0可以认为是一个空指针。
// 下面这三种是等效的,可以编译通过,但运行时会报错
std::string s = '\0';
std:string s = NULL;
std::string s= 0;
运行时报错:terminate called after throwing an instance of ‘std::logic_error’
what(): basic_string::_M_construct null not valid
- 其实该错误,就是说不可以一块空的地址(指针)去构造string。String构造部分,这块的代码大体应该如下:
string(const char* str)
{
// some code
if (NULL == str) {
throw "terminate called after throwing an instance of 'std::logic_error'what(): basic_string::_M_construct null not valid";
}
// some code
}
总结
- 错误改正是很简单的,但找错误比较耗时。敲代码时一定要仔细,不可想当然。