这个例子只是一个简单的内存跟踪方案, 思路很简单.
Step 1. 对现有的内存内配的函数做一个包装.< 可用 windows核心编程 里面介绍的API拦截方案 >
Step 2. 申请的时候记录当前行号, 释放的时候取消记录.
Step 3. 进程结束的时候打印所有未释放的申请记录.
注释: 考虑到多线程问题, 为了避免读写记录的时候有线程的竞争现象, 所以每个线程都有自己独立的记录结构, 不做任何交互, 等到进程结束的时候才统一清算. 示例代码如下:
- #include <string>
- #include <map>
- #include <set>
- #ifdef _WIN32
- #include <windows.h>
- inline unsigned long
- currentThreadID(void){ return GetCurrentThreadId();}
- #ifdef _DEBUG
- inline void output(std::string strInfo)
- { ::OutputDebugStringA(strInfo.c_str()); }
- #else
- #include <iostream>
- inline void output(std::string strInfo)
- { std::cout << strInfo << std::flush; }
- #endif
- #endif
- // 记录内存分配情况的结构框架.
- struct MemoryRecords
- {
- std::map< unsigned long, std::map<void*,std::string> > m_AllocInfos;
- std::map< void*, unsigned long > m_freeInfos;
- ~MemoryRecords()
- {
- std::map< unsigned long, std::map<void*,std::string>
- >::iterator itOut = m_AllocInfos.begin();
- for ( ; itOut != m_AllocInfos.end(); ++itOut )
- {
- std::map<void*,std::string>::iterator itIn = itOut->second.begin();
- for ( ; itIn != itOut->second.end(); ++itIn )
- {
- bool needToOutputInfo = true;
- if ( m_freeInfos.find(itIn->first) != m_freeInfos.end() )
- {
- if ( m_freeInfos[itIn->first] > 0 )
- {
- m_freeInfos[itIn->first] -= 1;
- needToOutputInfo = false;
- }
- }
- if ( needToOutputInfo ) output(itIn->second);
- }
- }
- }
- };
- MemoryRecords g_memRecords;
- // 申请内存 的 入口包装函数.
- void * operator new(unsigned int size,char* file, int line)
- {
- char strLine[64] = {0};
- _itoa_s(line,strLine,10);
- char strBytes[64] = {0};
- _itoa_s(size,strBytes,10);
- std::string strInfo;
- strInfo.append(file).append("(").append(strLine).append(") : ");
- strInfo.append("Here are ").append(strBytes).append(" btyes memory missed to be free, please check !\n");
-
- void * memory = operator new (size);
- // 有内存的内配活动, 记录当前的文件和行号.
- g_memRecords.m_AllocInfos[currentThreadID()][memory] = strInfo;
- return memory;
- }
- // 释放内存 的 入口包装函数.
- void release(void * memory)
- {
- std::map<void*,std::string> & mapAlloc
- = g_memRecords.m_AllocInfos[currentThreadID()];
- std::map< void*, unsigned long > & mapFree
- =g_memRecords.m_freeInfos;
- if ( mapAlloc.find(memory) != mapAlloc.end() ) {
- // 有内存被释放, 如果和申请在同一个线程就直接清除记录.
- mapAlloc.erase(memory);
- } else { // 否则, 就记录这一次释放, 方便最后的清算.
- if (mapFree.find(memory) != mapFree.end() )
- mapFree[memory] = 1;
- else mapFree[memory] += 1;
- }
- operator delete(memory); memory = NULL;
- }
- #ifdef _DEBUG
- #define new new(__FILE__, __LINE__)
- #endif
最后附上简单的测试代码. 如下:
- void test_new()
- {
- int * p1 = new int;
- int * p2 = new int;
- release(p1); p1 = NULL;
- }
- int main()
- {
- test_new();
- return 0;
- }
我是在VC上面测试的,双击输出框的打印结果能直接定位到申请内存的位置. 如下:
- ..............
- d:\src-project\basictest\basictest\test.cpp(98) : Here are 4 btyes memory missed to be free, please check !
- 程序“[9624] basicTest.exe: 本机”已退出,返回值为 0 (0x0)。
阅读(1991) | 评论(0) | 转发(0) |