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
}
總結
- 錯誤改正是很簡單的,但找錯誤比較耗時。敲代碼時一定要仔細,不可想當然。