IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++ 内存泄露 -> 正文阅读

[C++知识库]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

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-28 07:31:54  更:2021-07-28 07:34:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/10 11:35:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码