Be alert to memory leak when using STL to manage pointer only






1.11/5 (25 votes)
Mar 5, 2004
1 min read

79192
for some novice of STL, like me, who might make some low level errors when trying to release memory
Introduction
As a beginner a STL, I had lots memory leak problems to deal with, and struggled to figure out what the problems were. There problems happen in the case of trying to use the STL container to manage the pointer only. At the beginning I thought that I did put the ojbects in the container, it turned out that I just put the addresses of my ojbects in.
Truely STL will take care of everything only we do the right thing I think. To the novice of STL like me, the problem is I didn't realize that I was just letting the container to manage the poniters only.
The lession tells me that if we just put the addresses in the container, then it is our responsibility to free the memory which are requested for the objects before losing the addresses information.
Usually the bedugger would inform the leak kindly, assuming Visual Studio is used. It must be that just the addresses were deleted not actually releasing the memory.
<br>For example,we are creating a object class capsulated with stl container vector:
Example code:
Below is the code doing the "wrong thing"?
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)); } }
Now, below code trys to the right thing:
// 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 }
Final words
That is all, and the other containers(list,map,etc) will have the same situation when you let them manage the pointer/address only.
Just remeber to delete elements (mean delete the actual object) first from the container classes before using operation such as erase(), clear() because these operation might just delete the poniters.
Good luck!
Acknowledgement
Thank you, Rolf! Thanks for pointing out some big mistakes