2.3.3 发现内存泄露
本部分未被标准接收,仅作为一个技巧。
做法:通过宏来重载new和new[]运算符。
思路:
1.头文件
#ifndef MEMCHECK_H #define MEMCHECK_H #include <cstddef>
void* operator new(std::size_t, const char*, long); void* operator new[](std::size_t, const char*, long); #define new new (__FILE__, __LINE__)
extern bool traceFlag; #define TRACE_ON() traceFlag = true #define TRACE_OFF() traceFlag = false
extern bool activeFlag; #define MEM_ON() activeFlag = true #define MEM_OFF() activeFlag = false
#endif
|
注意:当需要跟踪动态存储区活动时,在最后一个头文件包含该文件。
2.实现文件
文件结构:
-
全局跟踪开关变量
-
匿名空间
- Info结构体
- 全局内存管理数组
- 查找和删除数组元素的api
- 自动析构以检测内存泄露的全局变量Sentinel
-
重载全局new和new[]
-
重载全局delete和delete[]
#include <cstudio> #include <cstdlib> #include <cassert> #include <cstddef> using namespace std; #undef new
bool traceFlag = true; bool activeFlag = false;
namespace { struct Info{ void* ptr; const char* file; long line; }; const size_t MAXPTRS = 10000u; Info memMap[MAXPTRS]; size_t nptrs = 0; int findPtr(void* p) { for(size_t i = 0;i<nptrs;i++) { if(memMap[i].ptr == p) return i; } return -1; } void delPtr(void* p) { int pos = findPtr(p); assert(pos >= 0); for(size_t i = pos; i < nptrs - 1;i++) { memMap[i] = memMap[i+1]; } --nptrs; } struct Sentinel { ~Sentinel(){ if(nptrs > 0) { printf("Leaked memory at:\n"); for(size_t i = 0;i < nptrs;i++) { printf("\t%p (file: %s, line: %ld)\n", memMap[i].ptr, memMap[i].file, memMap[i].line); } } else printf("No user memory leaks!\n"); } }; Sentinel s; }
void* operator new(size_t siz, const char* file, long line) { void* p = malloc(siz); if(activeFlag) { if(nptrs == MAXPTRS) { printf("memory map too small! (increase MAXPTRS)\n"); exit(1); } memMap[nptrs].ptr = p; memMap[nptrs].file = file; memMap[nptrs].line = line; ++nptrs; } }
void* operator new[](size_t siz, const char* file, long line) { return operator new(siz, file, line); }
void operator delete(void* p) { if(findPtr(p) >= 0) { free(p); assert(nptrs > 0); delPtr(p); if(traceFlag) { printf("delete memory at address %p\n", p); } else if(!p && activeFlag) { printf("Attempt to delete unknown pointer: %p\n", p); } } }
void operator delete[](void* p) { operator delete(p); }
|
3.使用
#include "MemCheck.h"
int main() { MEM_ON(); ... MEM_OFF(); }
|