65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 STL 管理指针时要警惕内存泄漏

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.11/5 (25投票s)

2004年3月5日

1分钟阅读

viewsIcon

79831

对于像我这样的 STL 新手,在使用时可能会犯一些低级错误,导致内存泄漏。

引言

作为 STL 的初学者,我遇到了很多内存泄漏问题,并且苦苦挣扎于找出问题所在。这些问题发生在尝试使用 STL 容器仅管理指针的情况下。一开始我以为我已经将对象放入容器中,结果我只是放了对象的地址进去。

真正的情况是,只要我们做对了,STL 会处理一切。对于像我这样的 STL 新手来说,问题在于我没有意识到我只是让容器管理指针而已。

这个教训告诉我,如果我们只是将地址放入容器中,那么释放为对象请求的内存就是我们的责任,在丢失地址信息之前。


通常,调试器会友好地提示泄漏,假设使用了 Visual Studio。这一定是仅仅删除了地址,而没有真正释放内存。



例如,我们创建一个用 STL 容器 vector 封装的对象类:

示例代码:

下面是执行“错误操作”的代码?

typedef std::vector<CObject *> ObjectVector;
class CObjectVector : public CObject
{
 DECLARE_SERIAL(CObjectVector);
// Construction
public:
 CObjectVector();

// Attributes
public:

// Operations
public:

// override
public:
 //{{AFX_VIRTUAL(CObjectVector)
 public:
 virtual void Serialize(CArchive& ar);
 //}}AFX_VIRTUAL
 
// Implementation
public:
 void RemoveObject(int nIndex);
 void RemoveAll();
 void AddObject(CObject object);
 virtual ~CObjectVector();

private:
 ObjectVector m_ObjectVector;
 
 //Object relate
private:

};

CObjectVector::CObjectVector(){
} 
  // before doing this, make sure what are deleted
CObjectVector::~CObjectVector(){
   m_ObjectVector.clear(); // Deletes all elements from the vector, which might be just the addresses information.                           
} 
 // same as above
void CObjectVector::RemoveAll(){   
   m_ObjectVector.clear(); // clear everything in the container
} 
 
void CObjectVector::RemoveObject(int nIndex){
   Vector<CObject*>::iterator  where = m_ObjectVector[nIndex];   
    // Yep, just delete the address
   m_ObjectVector.erase(where);  // Deletes the vector element pointed to by the iterator position
} 
  
 void CObjectVector::AddObject(CObject* object){
    m_ObjectVector.push_back(object);
}

void CObjectVector::Serialize(CArchive& ar){

 if (ar.IsStoring())


 { // storing code

   // store the vector
   /* code below is not correct,just for demostration */
   for(i=0;i<m_ObjectVector.size();i++){
       ar << m_ObjectVector[i];
   }
 
 }
 else
 { // loading code



    RemoveAll();
   /* code below  is not correct,just for demostration */       
    CObject* object;
    for(i=0;i<m_nWordsCount;i++){ 
      ar >> object;
      AddObject(object));
   }

}

现在,下面的代码尝试执行正确操作

// if the elements of container are the pointers of the objects 
CObjectVector::~CObjectVector(){
   for(int i=0;i<m_ObjectVector.size();i++)
      delete m_ObjectVector[i]; // free memory
   m_ObjectVector.clear(); // Deletes all elements from the vector.

}

 

// seems alright void CObjectVector::RemoveAll(){       for(int i=0;i<m_ObjectVector.size();i++)       delete m_ObjectVector[i];    m_ObjectVector.clear(); }

// correct? I hope so void CObjectVector::RemoveObject(int nIndex){    delete m_ObjectVector[nIndex]; // free one elemet memory    Vector<CObject*>::iterator  where = m_ObjectVector[nIndex];    m_ObjectVector.erase(where);  // Deletes the vector element pointed to by the iterator position }

最后的寄语


就这些了,其他容器(list、map 等)在您仅让它们管理指针/地址时,也会出现相同的情况。
请记住,在使用 erase()、clear() 等操作之前,先从容器类中删除元素(意味着删除实际对象),因为这些操作可能只是删除指针。
祝您好运!

致谢


感谢 Rolf!感谢您指出了许多错误。

© . All rights reserved.