Crime Scene Investigation—都是指针惹的祸

C++的魅力在于既能通过指针实现较底层地址操作,又能很好体现出面向对象的威力。在享受它的灵活性的同时,你必须具有坚实的C基础,时刻提防指针可能给你带来的灾难。可能很多程序员对此不以为然,对自己的C++水平满怀信心。但是我遇到很多程序员面试的时候就倒在了一个个具体的C++细节上。多年工作的老鸟也不敢轻易说自己的c++水平100分。至于本人自己,因为经常穿梭于C++C#managed code混用环境,也有陷入混乱的时候。下面就举一个例子讲讲我最近犯过的一个错误。

问题起始于我发现自己的一段程序经常crash,出现了一个严重的bug

这是一段什么样的程序呢?我定义的一个类里边要保存一个map集合,mapKeyValuePair中的value部分保存的是一个以数据集和为主的类对象:

class StyleInfo

{

public:      

       ~StyleInfo(){…};    

 

 

public:

       AcPpStyle *pStyle;  

 

       CString strLocStyleName;

       CString strDescription;

   

       //color

       AcCmColor AcCmColor;

 

       //layer info   

       CString strLayer;

… …

}

 

 

class MyClass

{

… …

 

private:

       std::map<int, StyleInfo> m_StyleMap;

      

… …

}

 

pStyle指向堆内存,当我在StyleInfo的析造函数里给指针对指针完成delete操作并赋值为NULL时,我莞尔一笑,庆幸自己时刻提防着内存泄漏。可是程序运行起来之后我就傻了眼。还好本人很快反应过来,以下肯定是问题的所在。

StyleInfo styleLocal = m_StyleMap[index];

 

局部对象一出作用域,析构函数岂不是就把我辛辛苦苦分配的堆对象析构了?怎么办?哥们灵机一动,反正指针赋指指的是同一地址,我就在在StyleInfo的析构函数里加上逻辑判断,决定什么时候该delete指针,什么时候不该。因为本人进行的是图形开发,new出来的对象有时需要交给图像平台去管理,这样一来程序员就不需要再进行delete操作回收空间,只需把指针赋NULL,否则就必须程序员自己打理。逻辑是复杂的,中午是发困的,10几分钟之后我能想到的漏洞都补齐了。此时我已经把delete相关的代码搬到MyClass的析构函数中了:

StyleInfo style = m_StyleMap[index];

 

AcPpStyle *pStyle = style.pStyle;

if(Acad::eOk == es && !id.isNull() && id.isValid())

{

       if (pStyle->isKindOf(AcPpAnnotationStyle::desc()))

       {

              AcDbObjectId btrId;

              btrId = pStyle->blockTableRecord();

              AcPpImpAnnotation::addAnnotationDataToBlockDef(btrId, pStyle->objectId());

       }// 以上是对像托付给图形平台的一些逻辑代码

 

       pStyle->close();

       pStyle = NULL;                   

}

 

 

MyClass::~ MyClass ()

{     

       for(int i=0; i<m_StyleMap.size(); i++)

       {            

              AcPpStyle *pStyle = m_StyleMap[i].pStyle;

              if(pStyle != NULL)

              {

                     delete pStyle;

                     pStyle = NULL;

              }

       }

}

 

终于可以开心的F5了,怎么回事,又出问题了!哥哥这个时候开始犯糊涂了,难道操作map的时候,StyleInfo类缺省赋值不起作用了?好吧,给StyleInfo重载赋值操作符,明确指针的指向,把指针成员的赋指指向同一个块儿内存。还不行?加一个拷贝构造函数, 还是不行!(我对自己否定自己的C++对象模型知识感到很惋惜!明眼人可以靠到我在犯罪的道路上越走越远。 J)哥们出离愤怒了,这么几行代码就要摧毁我的职业信心?昏昏欲睡的脑袋频率是越来越低。怎么办?喝杯冷水去。

一杯冷水下肚,老袋清醒一圈,原因自明了:

 

 

缺省的指针赋指会将其和map中的指针指向同一地址不假。但是当我把local对象中的指针delete或清零时,map中的指针指向的内容确实不存在了,但是指针本身还是指向以前的堆内存地址,此刻如果进行地址访问必将出现问题。因此我必须把map里的指针也同时清零。Oh, my God!

 

可见C++中的很多东西,你不仅要记规律,更要明白其中的道理,最重要的还是要灵活应用它们,时刻提防着它们。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值