然后在网上搜索了半天,找到一篇用gdb调试的文章,简而言之就是编译是加-g选项,然后用gdb ./test 来调试,试了一下,确实是在mysql clsoe的时候,调用free_root的时候,在my_alloc.c里面出现错误,但是居然提示找不到my_alloc.c,叉叉啊。
冷静的想了一下,应该不会是mysql的错误,要不之前的代码岂不是问题很多。接下来采用屏蔽代码的办法,发现确实是一段代码对内存操作存在问题,由于是老代码,当时看了有疑问,但是想如果出问题的话早就有问题了,就没多想。
上代码:
C++语言: 高亮代码由发芽网提供
01 while ((row = mysql_fetch_row(res)) != NULL)
02 {
03 k++;
04 pColLen = mysql_fetch_lengths(res);
05
06 if(NULL != row && NULL != pColLen)
07 {
08 for(int i=0; i < num_fields; i++)
09 {
10 memset(aryColValue, 0, 1024);
11 if (pColLen[i] > 1024)
12 {
13 printf("Error:%d\r\n",pColLen[i]);
14 printf("Error:%s\r\n",row[i]);
15 }
16 memmove(aryColValue, row[i], pColLen[i]);
17 if(utf8Flag==1)
18 {
19 strFieldValue = Utf8ToGbk(aryColValue);
20 }
21 else
22 {
23 strFieldValue = aryColValue;
24 }
25 if(!tmpresult.insert(std::map<std::string, std::string>::value_type(fields[i].name, strFieldValue)).second)
26 {
27 dblog.WriteLog( "Error:tmpresult.insert(%s)失败\n",strFieldValue.c_str());
28 }
29 }
30 result.push_back(tmpresult);
31 tmpresult.clear();
32 }
33 }
memset(aryColValue, 0, 1024);
memmove(aryColValue, row[i], pColLen[i]);
这两句真是坑爹啊,aryColValue只有1024个字节,但是pCollen表示每个字段的长度,很有可能超过1024字节的,而且我看了数据库里面相关字段,是mediumtext类型,最大长度2的24次方-1个字节。这代码,无语了。而且看了其他一些代码,也是有最多1024*5个字节,这太乱来了吧。就是这段代码,直接导致内存操作越界了。
修改为tmpresult[fields[i].name] = row[i];tmpresult是一个map<string,string>,string长度至少是32位的,够用了。
我发现这老代码真是不可相信啊,各种乱来。预期后续可能还会碰到不少问题,这样看了我还要搞不少时间啊。
这两句真是坑爹啊,aryColValue只有1024个字节,但是pCollen表示每个字段的长度,很有可能超过1024字节的,而且我看了数据库里面相关字段,是mediumtext类型,最大长度2的24次方-1个字节。这代码,无语了。而且看了其他一些代码,也是有最多1024*5个字节,这太乱来了吧。就是这段代码,直接导致内存操作越界了。
修改为tmpresult[fields[i].name] = row[i];tmpresult是一个map<string,string>,string长度至少是32位的,够用了。
我发现这老代码真是不可相信啊,各种乱来。预期后续可能还会碰到不少问题,这样看了我还要搞不少时间啊。
没有评论:
发表评论