删除void*指针引发的内存泄露

When a void* points to a class object, performing a delete operation on it will lead to undefined behavior—it is certain that this delete operation will not call the object’s destructor, resulting in a memory leak.

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
class Foo{
public:
Foo(char* name){
m_name=name;
m_data=new char[100];
};
~Foo(){delete[] m_data;};
private:
char* m_data;
char* m_name;
};
// Defines a function specifically for releasing class objects, using void* to allow any type of object to be released by this function
void GeneralDelete(void* ptr){
delete ptr;
}
int main(int argc,char* argv[])
{
Foo* foo=new Foo("foo");
// Intending to call GeneralDelete to execute Foo's destructor
GeneralDelete(foo);
return 0;
}

This code compiles without issues.

However, through gprof analysis, it can be found that Foo’s destructor was not called:

In the above code, a GeneralDelete function is defined for uniformly releasing dynamically allocated objects. The parameter of this function is declared as void*, indicating that any type of object can be released uniformly.

Here, when calling GeneralDelete to release the foo object, it is first cast to void*, then deleted. But the problem arises here: deleting the void* type of foo leads to memory leak because when using the delete operator to release an object, delete needs to correctly release the memory block pointed to by the pointer based on type information. The working principle of the delete operator can be roughly represented by the following pseudo code:

1
2
3
4
delete(obj *ptr){
call_destructors(ptr);
free(ptr);
}

That is, first call the object’s destructor, then release the object pointer. Before calling an object’s destructor, it is first necessary to know the object’s type; if the type of the object is unknown, it cannot be determined whose destructor to call.

Since the object foo passed to the function is converted to void*, delete will not call any destructors, and thus the dynamically allocated memory in the constructor is not released, leading to a memory leak.

The C++ standard clearly states that performing a delete operation on a void* pointer will cause undefined behavior. Therefore, try to avoid converting a regular object to void* type, and do not perform delete operations on void* objects.

The code for correctly performing a delete operation is:

1
2
3
4
5
6
int main(int argc,char* argv[])
{
Foo* foo=new Foo("foo");
delete foo;
return 0;
}
The article is finished. If you have any questions, please comment and communicate.

Scan the QR code on WeChat and follow me.

Title:删除void*指针引发的内存泄露
Author:LIPENGZHA
Publish Date:2016/06/04 10:51
World Count:1.5k Words
Link:https://en.imzlp.com/posts/6978/
License: CC BY-NC-SA 4.0
Reprinting of the full article is prohibited.
Your donation will encourage me to keep creating!