最近某应用跑压力测试的时候出现了下面的错
[2012-07-31 22:33:59:271046, db_mgr.cpp:GetDeviceInfo:1129, DBG , 0xb35f4b90]: select object_id, object_name, object_type_id, class_type_id, device_type_id from m_object where object_id = 225663102
terminate called after throwing an instance of 'std::logic_error' what(): basic_string::_S_construct NULL not valid
首先我对
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct NULL not valid这个报错信息是陌生的....
所以我直接到文件
db_mgr.cpp:GetDeviceInfo:1129去定位错误,并没太多收获,文件的内容为
g_log.LogTextEx(DBG, "%s", oss.str().c_str());
我只能间接查出设备 225663102 所属的基站,
发现里面还没有基础信息的xml文件中,所以进一步缩窄范围.
所以基本定义到了GetDeviceInfo的调用者 XMLMaker::GenBaseInfo 中了
再根据出错的提示,网上说这个出错信息是用空指针去构造string会出问题,
有下面类似的说明
std::string 的初始化碰到一个问题, 拿一个 char* 的指针当构造函数的指针, 运行时出现:
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct NULL not valid已放弃
原因在于没搞清, char *型的变量和指向 c 风格的字符串指针的区别.
char *cp = NULL; cp是一个char*变量
char *str = "Hello"; str是一个指向 c 风格的字符串指针.
std::string 的构造函数需要的是一个 c 风格的字符串指针(要求以字符 null 结尾), 而不是一个char *的变量. 所以运行时出了上述错误.
另外, 很多 c 标准函数, 函数明确说明, 需要一个 c 风格的字符串. 虽然char * 和指向 c 风格的字符串指针的代码看起来都是 char *, 但是含义上有本质的区别.
所以为此,我特意在开发机上写下如下的测试代码
1 #include2 #include 3 4 using std::string; 5 6 7 int main(int argc, const char *argv[]) 8 { 9 string str = NULL; 10 std::cout << str << std::endl; 11 return 0; 12 }
compile没问题,运行时确报错
:!a.out
terminate called after throwing an instance of 'std::logic_error' what(): basic_string::_S_construct NULL not validCommand terminated
这个报出来的错误信息基本上与我之前应用的相似的,
信息足够定位了,于是我就在方法
XMLMaker::GenBaseInfo中打一些string 的构造
发现了如下关于转码的一句.
1 string str_tmp = g2u(const_cast(di.object_name.c_str())); 2 xmlNewChild(node_lv2, NULL, BAD_CAST "object_name", 3 BAD_CAST str_tmp.c_str());
而再追到
1 //GB2312码转为UNICODE码 2 //成功则返回一个动态分配的char*变量,需要在使用完毕后手动free,失败返回NULL 3 char* g2u(char *inbuf) 4 { 5 int nOutLen = 2 * strlen(inbuf) - 1; 6 char* szOut = (char*)malloc(nOutLen); 7 8 if (-1 == code_convert("gb2312","utf-8",inbuf,strlen(inbuf),szOut,nOutLen)) 9 { 10 free(szOut); 11 szOut = NULL; 12 } 13 return szOut; 14 } 15
发现从其它地方挪过来的代码居然会返回NULL看来要作出特殊处理才行了.
这样,这个问题就基本定位,剩下就是修改并回归测试了