? ? 内存泄露是C++程序中比较常见的问题,产生的原因就是new了一片内存,没有delete. 解决方法可以分两种,一种是通过辅助工具如: linux下的Valgrind, Windows下的UMDH先定位出问题点,然后再修复.
? ? ?另一种通过修改代码,改用智能指针shared_ptr(注意和weak_ptr配合使用).或者重写new/delete,将每次new的信息记录下来.
? ? ?本文将重点讲解通过重载 operator new/delete 来定位内存泄露. 见代码:
// 内存记录
class MemInfo {
private:
void* ptr;
const char* file;
unsigned int line;
MemInfo* next;
friend class MemStack;
};
// 内存记录栈
class MemStack {
private:
MemInfo* head; // 链表头
public:
MemStack() :head(nullptr) {}
~MemStack() {
MemInfo* tmp = nullptr;
while (head != NULL)
{
free(head->ptr); // 释放泄漏的内存
tmp = head->next;
free(head);
head = tmp;
}
}
// 将每次new的信息保存起来
void Insert(void* ptr, const char* file, unsigned int line) {
MemInfo* node = (MemInfo*)malloc(sizeof(MemInfo));
node->ptr = ptr; node->file = file; node->line = line;
node->next = head; head = node; // 形成一个链表
}
void Delete(void *ptr) {
MemInfo* node = head; // 取到链表头
MemInfo* pre = nullptr;
while (node != NULL && node->ptr != ptr) // 根据ptr找到对应的结点
{
pre = node;
node = node->next;
}
if (node == NULL)
cout << "delete a new block memory" << endl;
else {
if (pre == NULL) // 删除的是head
head = node->next;
else
pre->next = node->next;
free(node);
}
}
void Print() {
if (head == NULL) {
cout << "All deleted" << endl;
return;
}
cout << "memory leak" << endl;
MemInfo* node = head;
while (node!=NULL)
{
cout << "filename: " << node->file << ", " << "line: " << node->line << ", "
<< " addr: " << node->ptr << endl;
node = node->next;
}
}
};
// 全局对象mem_stack记录开辟的内存
MemStack mem_stack;
// 重载new/delete
// C++规定重载new时,第一个参数必须是size_t size
void* operator new(size_t size, const char* file, unsigned int line){
void* ptr = malloc(size);
mem_stack.Insert(ptr, file, line);
return ptr;
}
void* operator new[](size_t size, const char* file, unsigned int line) {
return operator new(size, file, line);
}
void operator delete(void* ptr) {
free(ptr);
mem_stack.Delete(ptr);
}
void operator delete[](void* ptr) {
operator delete(ptr);
}
#define new new(__FILE__, __LINE__) // 这是关键!!!
void bad_code() {
int *p = new int;
char* q = new char[5];
delete[] q;
}
void good_code() {
int *p = new int;
char *q = new char[5];
delete p;
delete[]q;
}
int main()
{
good_code();
bad_code();
mem_stack.Print();
system("PAUSE");
return 0;
}
参考:
https://blog.csdn.net/Zhanganliu/article/details/88027760?spm=1001.2014.3001.5501
|