随笔-89  评论-224  文章-23  trackbacks-0
   最近在工作中,写一计算杆塔绝缘子中心点的GPS坐标程序时,定义了一结构,里面用到了string类型来存储杆塔所属线路号、杆塔号,杆塔模型名称。代码如下:
 1/*
 2  @brief 杆塔信息结构
 3*/

 4typedef struct   _TOWER_INFO
 5{
 6       string    strLineNo;           ///< 线路号 
 7       string    strTowerNo;         ///< 杆塔号
 8       string    strTowerType;     ///< 杆塔类型
 9       double  dDangDistance;    ///< 档距
10      double  dHCHeight;           ///< 呼称高
11      double  dLongitude;          ///< 经度
12      double  dLatitude;              ///< 纬度
13      double  dAltitude;              ///< 海拔高度
14      double  dLineCorners;      ///< 线路转角 
15      long      lCornerDirection;  ///< 左转还是右转: 0不转, 1左转, 2右转
16      vector<INSULATOR_INFO::CENTER_POINT_INFO>  vecInsulatorCenterPointInfo; ///< 杆塔所有绝缘子中心点信息
17       _TOWER_INFO() { memset(this0sizeof(_TOWER_INFO)); }       //该行代码可能会引起string内存泄露
18
19}
TOWER_INFO,*PTOWER_INFO;
   在后面对该结构的string型变量有赋值操作, 代码如下
1   ......
2       TOWER_INFO cur_tower_center_info;
3   cur_tower_center_info.strLineNo = sheetLine->Cell(i, 2)->GetText(); //调度码
4   cur_tower_center_info.strTowerNo = sheetLine->Cell(i, 7)->GetText(); //杆塔号
5   cur_tower_center_info.strTowerType = sheetLine->Cell(i, 8)->GetText(); //杆塔类型
6      ......
   运行程序,待程序结束后,发现有内存泄露,提示信息如下
 1Detected memory leaks!
 2Dumping objects ->
 3{235250} normal block at 0x01774A6016 bytes long.
 4 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
 5{235237} normal block at 0x01774CB016 bytes long.
 6 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
 7{235234} normal block at 0x01774A1016 bytes long.
 8 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
 9{235184} normal block at 0x0177420016 bytes long.
10 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
11{235171} normal block at 0x0177445016 bytes long.
12 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
13{235168} normal block at 0x017741B016 bytes long.
14 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
15{235118} normal block at 0x017739A016 bytes long.
16 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
17{235105} normal block at 0x01773BF016 bytes long.
18 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
19..
   经过一番源代码跟踪调试后,发现原因在于TOWER_INFO结构体的构造函数内调用了memset(this, 0, sizeof(_TOWER_INFO);使得string内部指针_Bx._Ptrr值为0,_Myres为0,在这种情况下当string对象被赋值为小字符串(字节数包括结束符小于等于16的字符串)时,因新申请的内存在后来得不到释放,所以这块内存被泄露了,根据string类内存管理算法(ms vc版本)得知这块内存大小总是16个字节.但当被赋值为大字符串(字节数包括结束符大于16的字符串)时,反而没有内存泄露,这是因为新申请的内存在析构或下次赋值时总能被释放.
  从该泄露问题的分析解决过程中,总结得到规律:不要轻易零初始化string, vector等stl标准容器及具有动态内存管理的类。
posted on 2009-08-07 01:31 春秋十二月 阅读(5306) 评论(19)  编辑 收藏 引用 所属分类: C/C++

评论:
# re: std::string内存泄露问题之分析解决 2009-08-07 06:24 | maomi
凡是初始化有非零赋值的都有问题,和有没有动态内存管理无关吧
vector 似乎没事,都是零初值  回复  更多评论
  
# re: std::string内存泄露问题之分析解决 2009-08-07 07:44 | shaker(太子)
问题是你为什么要用memset去操作一个对象?  回复  更多评论
  
# re: std::string内存泄露问题之分析解决 2009-08-07 08:32 | 周龙亭
问题在于你用memset操作C++对象  回复  更多评论
  
# re: std::string内存泄露问题之分析解决[未登录] 2009-08-07 08:56 | christanxw
楼主难道就不知道C++类构造函数不要随便使用memset去初始化对象吗?一切问题都是你的memset引起的,跟string没关系。  回复  更多评论
  
# re: std::string内存泄露问题之分析解决 2009-08-07 09:20 | evoup
这都敢用memset this,汗~  回复  更多评论
  
# re: std::string内存泄露问题之分析解决 2009-08-07 09:36 | abettor
作为博主忠实的粉丝,为了拥护博主的文章,我也曾经犯过几乎相同的错误。
我当时是在VC6里把含有CString型成员的结构体给memset了。  回复  更多评论
  
# re: std::string内存泄露问题之分析解决 2009-08-07 12:39 | 陈梓瀚(vczh)
就算是struct,我也会写一个构造函数,从而代替memset的……其实在使用的过程中,memset基本没用处  回复  更多评论
  
# re: std::string内存泄露问题之分析解决 2009-08-07 12:53 | test
memset(this, 0,。。本身没问题,但是前提条件是它内部成员是你可控的。这是c程序员向c++程序员转换的时候的一个阶段。。。  回复  更多评论
  
# re: std::string内存泄露问题之分析解决 2009-08-07 13:10 | CY
楼上说得好。
应该总结:不要从内存级别改变对象级别的东西  回复  更多评论
  
# re: std::string内存泄露问题之分析解决 2009-08-07 14:15 | zdhsoft
不要把C的习惯带入C++
  回复  更多评论
  
# re: std::string内存泄露问题之分析解决 2009-08-07 20:33 | 空明流转
变成批判大会了。。。  回复  更多评论
  
# re: std::string内存泄露问题之分析解决 2009-08-08 16:45 | lovelypig
标题党  回复  更多评论
  
# re: std::string内存泄露问题之分析解决 2009-08-11 10:51 |
。。。。楼主太NB了  回复  更多评论
  
# re: std::string内存泄露问题之分析解决 2009-08-13 09:43 | bigzhu
不要混用c和c++
不然就是这样悲惨的遭遇..
楼主改下题目吧
不要把泄漏赖到string头上...  回复  更多评论
  
# re: std::string内存泄露问题之分析解决 2009-11-15 11:12 | calabash
我也遇到了同样的问题,哎,调查半天。。。

//应该总结:不要从内存级别改变对象级别的东西
这个很有道理  回复  更多评论
  
# re: std::string内存泄露问题之分析解决[未登录] 2010-06-18 09:21 | kuafoo
这个属于使用不当  回复  更多评论
  
# re: std::string内存泄露问题之分析解决 2011-08-26 12:28 | 匿名
我也遇到同样的问题:
我声明一个结构体,如下:
struct A
{
int id;
string name;
};

A a;
a.id = 9;
a.name = "tom";
想把该结构体内容拷贝到char* buff中,用memcpy(buff,&a,sizeof(a));

在此过程中,如果a.name长度小于16,结果与期望一致,但是如果a.name的长度大于16,则出现问题,通过调试发现再把buff中的内容拷贝回a,则显示a的name属性是不可读内容。  回复  更多评论
  
# re: basic_string内存泄露问题之分析解决 2012-04-11 10:50 | CCW
想把该结构体内容拷贝到char* buff中,用memcpy(buff,&a,sizeof(a));
是memcpy(buff,&a.name,sizeof(a.name));吧
@匿名  回复  更多评论
  
# re: basic_string内存泄露问题之分析解决 2014-09-09 17:18 | 席大军
如果 吧struct中的string都换成char数组,可以用memset吗?  回复  更多评论
  

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理