【C++】小项目——内存泄露检测器

来源:互联网 发布:windows桌面分类框 编辑:程序博客网 时间:2024/05/30 22:52

    在C++中,指针往往忘记释放。引起内存泄露。

1.内存泄露指:

    内存泄漏也称作“存储渗漏”,用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。(其实说白了就是该内存空间使用完毕之后未回收)即所谓内存泄漏。

    内存泄漏形象的比喻是“操作系统可提供给所有进程的存储空间正在被某个进程榨干”,最终结果是程序运行时间越长,占用存储空间越来越多,最终用尽全部存储空间,整个系统崩溃。所以“内存泄漏”是从操作系统的角度来看的。这里的存储空间并不是指物理内存,而是指虚拟内存大小,这个虚拟内存大小取决于磁盘交换区设定的大小。由程序申请的一块内存,如果没有任何一个指针指向它,那么这块内存就泄漏了。

    然后今天做了一个内存泄露检测工具,准确来说是定义了一个接口,通过这个接口来实现类存泄露的解决。

    

2.设计思路:

    通过自己定义的接口,将我们开辟的指针都存储到一个指针相关信息的链表中。将链表定义为全局变量。然后通过全局变量来确定我们所有动态开辟空间的详细信息表,也可以使用单例模式来解决。大概的图解就是:wKiom1Z-Sj_h_4jZAAA1t9XeL1w714.png然后我们首先定义出节点类型:

structMemListNode{void* _ptr;string _file;int _line;//只用书写构造函数MemListNode(void* ptr = 0,const char* file = "",int line = 0):_ptr(ptr),_file(file),_line(line){}};

然后我们定义全局变量,利用宏命令,模板,还有类型萃取完成我们内存泄露检测的功能实现:

MemoryCheck.hpp

#include <iostream>#include<assert.h>#include<list>#include<string>#include"TypeTraits.hpp"using namespace std;#define NEW(type)\__new<type>(sizeof(type),__FILE__,__LINE__)#define DELETE(type,ptr)\__delete<type>(ptr)#define NEW_ARRAY(type,num)\__newArray<type>(sizeof(type)*num+4,__FILE__,__LINE__,num)#define DELETE_ARRAY(type,ptr)\__deleteArray<type>(ptr)structMemListNode{void* _ptr;string _file;int _line;//只用书写构造函数MemListNode(void* ptr = 0,const char* file = "",int line = 0):_ptr(ptr),_file(file),_line(line){}};list<MemListNode> MemList;void* Alloc(size_t size,const char* file,int line){void *ptr = malloc(size);if(ptr){MemListNode info(ptr,file,line);MemList.push_back(info);}return ptr;}void Dealloc(void* ptr){void* del = ptr;if(ptr){list<MemListNode>::iterator it = MemList.begin();while(MemList.end() != it){if(it->_ptr == ptr){MemList.erase(it);free(del);return;}++it;}printf("释放的指针没有申请空间\n");}}template<class T>T* __new(size_t size,const char* file,int line){T* ptr = (T*)Alloc(size,file,line);if(TypeTraits<T>::__IsPODType().Get()){return ptr;}else{return new(ptr) T;}}template<class T>void __delete(T* ptr){if(TypeTraits<T>::__IsPODType().Get()){Dealloc(ptr);}else{ptr->~T();Dealloc(ptr);}}template<class T>T* __newArray(size_t size,const char* file,int line,size_t num){T* ptr = (T*)Alloc(size,file,line);if(TypeTraits<T>::__IsPODType().Get()){return ptr;}else{*(int *)ptr = num;T* cur = (T*)((int)ptr+4);for(int i =0;i < num;++i){new(cur)T;cur = (T*)((int)cur + sizeof(T));}return ptr;}}template<class T>void __deleteArray(T* ptr){if(TypeTraits<T>::__IsPODType().Get()){Dealloc(ptr);}else{int num = *((int *)ptr);T* cur = (T*)((int)ptr+4);for(int i = 0;i < num;++i){cur->~T();cur = (T*)((int)cur + sizeof(T));}Dealloc(ptr);}}void print(){list<MemListNode>::iterator it = MemList.begin();if(MemList.end() == it){cout<<"指针已经全部释放"<<endl;}while(MemList.end() != it){int i = 1;printf("%d:指针地址%p,文件名:%s,行号:%d\n",i++,it->_ptr,it->_file.c_str(),it->_line);++it;}}

    

类型萃取我们单独写一个文件:

#pragma once#include<iostream>using namespace std;struct __TrueType{bool Get(){return true;}};struct __FalseType{bool Get(){return false;}};template <class _Tp>struct TypeTraits{   typedef __FalseType  __IsPODType;};template <>struct TypeTraits< bool>{   typedef __TrueType     __IsPODType;};template <>struct TypeTraits< char>{   typedef __TrueType     __IsPODType;};template <>struct TypeTraits< unsigned char >{   typedef __TrueType     __IsPODType;};template <>struct TypeTraits< short>{   typedef __TrueType     __IsPODType;};template <>struct TypeTraits< unsigned short >{   typedef __TrueType     __IsPODType;};template <>struct TypeTraits< int>{   typedef __TrueType     __IsPODType;};template <>struct TypeTraits< unsigned int >{   typedef __TrueType     __IsPODType;};template <>struct TypeTraits< long>{   typedef __TrueType     __IsPODType;};template <>struct TypeTraits< unsigned long >{   typedef __TrueType     __IsPODType;};template <>struct TypeTraits< long long >{   typedef __TrueType     __IsPODType;};template <>struct TypeTraits< unsigned long long>{   typedef __TrueType     __IsPODType;};template <>struct TypeTraits< float>{   typedef __TrueType     __IsPODType;};template <>struct TypeTraits< double>{   typedef __TrueType     __IsPODType;};template <>struct TypeTraits< long double >{   typedef __TrueType     __IsPODType;};template <class _Tp>struct TypeTraits< _Tp*>{   typedef __TrueType     __IsPODType;};

简单的测试用例:

#include"MemoryChilke.hpp"#include"TypeTraits.hpp"void Test(){string* p1 = NEW(string);DELETE(string,p1);int *p2 = NEW(int);string* p3 = NEW_ARRAY(string,10);DELETE_ARRAY(string,p3);print();}int main(){Test();return 0;}

完成了。大家只要具备基本的知识,认真去看会做出来的。

本文出自 “剩蛋君” 博客,转载请与作者联系!

0 0
原创粉丝点击