内存泄漏及检测
2016-07-14 17:39
197 查看
一、What?
内存泄漏:由于程序员的疏忽或错误造成程序未能释放已不在使用的内存,导致减少可用内存,降低计算机性能,导致程序崩溃。
内存溢出:是指已有的数据超过了其获得到的内存所能存储的范围,比如用一个字节存放1000这个数字就属于内存溢出。
new之后没有delete,那么return后就会发生内存泄露。
虽然看上去这样并不造成什么严重后果,但是
这种也是人为错误,甚至会导致程序崩溃。
而在代码量很大的情况下并不好检查,所以需要使用工具来进行内存泄漏的检测,辅助我们找到内存泄漏代码的地方:某某文件、某某行。
二、How?
一种简单的检测方法:
1、原理:
C++有操作符重载的机制,所以可以通过重载 new、delete 操作符,来做一些处理。
每次执行 new 操作时,将指针和当前文件名称和行号保存在我们自己维护的一个容器里;执行 delete 时,将对应指针的项从容器中删除,最后程序结束时检查容器中是否还有未释放的指针。
2、实现:
(1)new操作符重载
(2)delete操作符重载
测试之后出现两个Bug
测试1::
new之后未释放结果检测内存泄漏了
测试2:
new 之后明明 delete 了,为什么还会出现内存泄漏呢?
原因是 new 了数组后执行的是 delete[] ,而重载的是 delete,所以容器里面指针的并没有删除,那么就需要重载 delete[]
测试3:
在前面两个测试中也出现了这样的异常崩溃。
首先,程序在加载时:
a、将程序加载到系统内存;
b、将原有 new 和 delete 全部替换;
c、程序需要执行 new 和 delete 的地方都被监管;
最后,程序卸载:
a、将程序中的对象析构;
b、对象被析构之后以及不存在;
c、此时 delete 和 new 里面还在使用这个对象,所以造成异常崩溃。
所以在类中添加一个 static bool Ready;构造函数初始化它为 true,析构函数让它为 false,在对象存在的时候才可以 new 和 delete。
代码地址:https://github.com/xyr129/MemChecker
内存泄漏:由于程序员的疏忽或错误造成程序未能释放已不在使用的内存,导致减少可用内存,降低计算机性能,导致程序崩溃。
内存溢出:是指已有的数据超过了其获得到的内存所能存储的范围,比如用一个字节存放1000这个数字就属于内存溢出。
int *p = new int; return 0;
new之后没有delete,那么return后就会发生内存泄露。
虽然看上去这样并不造成什么严重后果,但是
while(true) { int *p = new int; } return 0;
这种也是人为错误,甚至会导致程序崩溃。
而在代码量很大的情况下并不好检查,所以需要使用工具来进行内存泄漏的检测,辅助我们找到内存泄漏代码的地方:某某文件、某某行。
二、How?
一种简单的检测方法:
1、原理:
C++有操作符重载的机制,所以可以通过重载 new、delete 操作符,来做一些处理。
每次执行 new 操作时,将指针和当前文件名称和行号保存在我们自己维护的一个容器里;执行 delete 时,将对应指针的项从容器中删除,最后程序结束时检查容器中是否还有未释放的指针。
2、实现:
(1)new操作符重载
#define new new(__FILE__,__LINE__) void* operator new(size_t size, const char* file, long line) { void* p = malloc(size); mch.Add(p, file, line); //往容器中添加项 return p; }
(2)delete操作符重载
void operator delete(void* p) { mch.Remove(p); //删除容器中对应指针 free(p); }
测试之后出现两个Bug
测试1::
new之后未释放结果检测内存泄漏了
测试2:
new 之后明明 delete 了,为什么还会出现内存泄漏呢?
原因是 new 了数组后执行的是 delete[] ,而重载的是 delete,所以容器里面指针的并没有删除,那么就需要重载 delete[]
void operator delete[](void* p) { mch.Remove(p); free(p); }
测试3:
在前面两个测试中也出现了这样的异常崩溃。
首先,程序在加载时:
a、将程序加载到系统内存;
b、将原有 new 和 delete 全部替换;
c、程序需要执行 new 和 delete 的地方都被监管;
最后,程序卸载:
a、将程序中的对象析构;
b、对象被析构之后以及不存在;
c、此时 delete 和 new 里面还在使用这个对象,所以造成异常崩溃。
所以在类中添加一个 static bool Ready;构造函数初始化它为 true,析构函数让它为 false,在对象存在的时候才可以 new 和 delete。
#include "MemChecker.h" MemChecker mch; bool MemChecker::Ready = false; void* operator new(size_t size, const char* file, long line) { void* p = malloc(size); if (MemChecker::Ready) mch.Add(p, file, line); return p; } void operator delete(void* p) { if (MemChecker::Ready) mch.Remove(p); free(p); } void operator delete[](void* p) { if (MemChecker::Ready) mch.Remove(p); free(p); } MemChecker::MemChecker() { Ready = true; } MemChecker::~MemChecker() { Dump(); Ready = false; } void MemChecker::Add(void* pointer, const char* file, long line) { pointer_map_[pointer] = Entry(file, line); } void MemChecker::Remove(void* pointer) { auto iter = pointer_map_.find(pointer); if (iter != pointer_map_.end()) { pointer_map_.erase(iter); } } void MemChecker::Dump() { if (!pointer_map_.empty()) { cout << "内存泄露" << endl; for (auto iter = pointer_map_.begin(); iter != pointer_map_.end(); ++iter) { const char* file = iter->second.File(); long line = iter->second.Line(); cout << "在" << file << "\t" << line << "出现内存泄露" << endl; } } }
代码地址:https://github.com/xyr129/MemChecker
相关文章推荐
- c语言内存泄露示例解析
- 解决js函数闭包内存泄露问题的办法
- IE下使用jQuery重置iframe地址时内存泄露问题解决办法
- Android App调试内存泄露之Cursor篇
- js内存泄露的几种情况详细探讨
- Javascript 闭包引起的IE内存泄露分析
- JS闭包、作用域链、垃圾回收、内存泄露相关知识小结
- 深入解析PHP垃圾回收机制对内存泄露的处理
- PHP脚本内存泄露导致Apache频繁宕机解决方法
- 容易造成JavaScript内存泄露几个方面
- 关于js内存泄露的一个好例子
- 总结JavaScript在IE9之前版本中内存泄露问题
- Android垃圾回收机制解决内存泄露问题
- Android编程中避免内存泄露的方法总结
- C语言中的内存泄露 怎样避免与检测
- PHP CURL 内存泄露问题解决方法
- Java中典型的内存泄露问题和解决方法
- Android中Handler引起的内存泄露问题解决办法
- 浅谈Java编程中的内存泄露情况
- 理解Java中的内存泄露及解决方法示例