C++ 内存泄露

    内存泄露是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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值