Memory leak caused by STL releasing pointer elements

STL释放指针元素时造成的内存泄露

When we delete a pointer, the object it points to will be deleted. However, this does not happen when pointer objects are stored in an STL container.

1
2
3
4
5
// Deleting a pointer will delete the object to which the pointer points
int x=10;
int *p= &x;
// Deleting a pointer only deletes the memory space the pointer points to, without deleting the pointer itself; this pointer becomes a dangling pointer
delete p;

You can store objects in STL containers as well as pointers to objects. When STL objects call clear() or erase(), if the container holds object instances, they will be deleted. However, if the container holds object pointers, a memory leak occurs (only the pointers are deleted, but the objects they point to will not be deleted).

Consider the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// for(type varName:object) is a new feature in C++11 — range-based for loop.
vector<string*> strVector;
// Add ten string objects to strVector and initialize them to HelloWorld
for(int index=0;index<10;++index)
strVector.push_back(new string("HelloWorld!"));
// Create a copy of strVector
vector<string*> strVectorCopy=strVector;
// Output the pointer addresses stored in strVector and the objects they point to
for(auto &index:strVector)
cout<<index<<"\t"<<*index<<endl;
// Number of elements in strVector before releasing it
cout<<"strVector.size: "<<strVector.size()<<endl;
// Call clear() to delete all elements in strVector
strVector.clear();
// Or use erase to delete elements in strVector
/*
for(vector<string*>::iterator index=strVector.begin();index<strVector.end();){
strVector.erase(index);
}
*/
// Number of elements in strVector after releasing it
cout<<"strVector.size: "<<strVector.size()<<endl;

// Output all objects (pointers, i.e., the pointers originally stored in strVector) and the objects the pointers point to in strVectorCopy
for (auto &index:strVectorCopy)
cout<<index<<"\t"<<*index<<endl;

Running result:

It is clear from the results that although we called strVector.clear()/erase() to delete all objects (pointers), (as expected) and hoped to free their memory, the objects pointed to by the pointers still exist, leading to a memory leak.

The objects pointed to by the pointers stored in the STL container will not be automatically released when clear()/erase() clears the objects.

This is because clear()/erase() automatically calls the destructor of each object to release it, but when the container holds object pointers, using clear() only calls the pointer’s destructor, and the destructor does nothing. Thus, a memory leak occurs.

At this point, we need to manually manage the memory ourselves.

We can manually delete each object pointed to by the pointers in strVector using delete:

1
2
3
4
5
6
7
for(auto &index:strVector){
delete index;
}
// Or use the iterator version
for(vector<string*>::iterator index=strVector.begin();index<strVector.end();++index){
delete *index;
}

Then we output the values of the objects pointed to by the pointers in strVectorCopy:

1
2
3
4
5
6
7
for(auto &index:strVectorCopy){
cout<<*index<<endl;
}
// Iterator version
for(vector<string*>::iterator index=strVectorCopy.begin();index<strVectorCopy.end();++index){
cout<<**index<<endl;
}

Running result:

It can be seen that the objects pointed to by the pointers stored in strVector have been released, and at this time, we are accessing the memory block pointed to by a dangling pointer, resulting in undefined behavior.

When using STL, the following two points should be noted:

  • STL containers operate by copying. When you put an element into a container, what is actually stored in the container is a copy of that element, and the memory for the copy is automatically allocated by the STL container. When you delete this element, the STL will call the destructor of that element itself to reclaim that memory.
  • If you put a pointer into the container, when deleting the element, the container is only responsible for reclaiming the memory occupied by the pointer itself, but will not reclaim the content pointed to by the pointer.
The article is finished. If you have any questions, please comment and communicate.

Scan the QR code on WeChat and follow me.

Title:Memory leak caused by STL releasing pointer elements
Author:LIPENGZHA
Publish Date:2016/05/08 13:51
Word Count:1.9k Words
Link:https://en.imzlp.com/posts/50773/
License: CC BY-NC-SA 4.0
Reprinting of the full article is prohibited.
Your donation will encourage me to keep creating!