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






1.11/5 (25投票s)
2004年3月5日
1分钟阅读

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!感谢您指出了许多错误。