本项目的主要目的就是使用C++实现一个内存泄漏检测的功能,主要是用于短期内存泄漏的检查器。

设计思路:

1.内存泄漏的产生是new操作后,没有执行delete。然而new和delete都是操作符,我们可以使用操作符重载。在new时记录相关信息,在delete时删除该信息。

2.需要记录和删除信息,那么我们可以创建一个结构体(类)保存需要的信息,并将其作为value, 申请空间的地址作为key保存在unordered_map容器中。

3.此时我们需要一个类去管理unordered_map,并且这个类最好设计为单例模式。

memcheck.h

#ifndef _MEMCHEKC_H_
#define _MEMCHEKC_H_
#include<iostream>
#include<unordered_map>struct MemInfo//存的是数据!new时的数据!
{MemInfo() = default;MemInfo(const char* mFile, unsigned long mLine, unsigned long mSize):file(mFile), line(mLine), size(mSize){}std::string file;//那个文件的程序创建的unsigned long line;//那一行创建的unsigned long size;//创建了多大
};//单例模式
class MemCheck{
private:static bool notfreememCheck;//判断memcheck是否被释放,如果被释放了,是不允许调用的static std::unordered_map<void*, MemInfo> _memPool;//存储每一个new对象的类型,和他所对应的MemInfo数据unsigned long _totalMemSize;//计算申请了的堆大小static MemCheck memcheck;//定义一个类对象自己!//这里只是申明,类属性需要定义。注意定义顺序非常重要public:MemCheck();~MemCheck();//每次new了的数据都要添加到_memPool中记录!static void setMemInfo(void* p, const char* file, unsigned long line, unsigned long size);//从记录中删除!static void deleteMemInfo(void* p);
};//对new和new[]进行重载!
void* operator new(size_t size, const char* file, unsigned long line);
void* operator new[](size_t size, const char* file, unsigned long line);//对delete和delete[]进行重载!
void operator delete(void* ptr);
void operator delete[](void* ptr);//对new进行宏定义,每次调用时,自动将参数file和line加入!
//这个宏定义会导致其他的文件new产生问题!
#ifndef _NEW_OVERLOAD_IMPLEMENTATION_
#define new new(__FILE__, __LINE__)
#endif#endif

memcheck.cpp

//定义这个宏,一定要加到抬头,防止对memcheck.h和memcheck.cpp进行new展开替换
#define _NEW_OVERLOAD_IMPLEMENTATION_//引入头文件
#include"memcheck.h"//这些类属性,都是放在静态全局区的,所以在释放的时候一定要注意入栈出栈的顺序
//memcheck要最后定义,才会最先释放,然后去调用析构
bool MemCheck::notfreememCheck = true;
std::unordered_map<void*, MemInfo> MemCheck::_memPool;
MemCheck MemCheck::memcheck;MemCheck::MemCheck(){}//因为没有new都是MemInfo对象,所以不需要释放空间
MemCheck::~MemCheck(){memcheck.notfreememCheck = false;std::cout << "==================MEMCHECK DESTRUCTOR===================\n";if(memcheck._memPool.size() > 0){//说明unordered_map内数据,有内存泄漏!std::cout << "--------leak memory info---------\n";for (auto it : _memPool){//这里相当于取map对象,所以用 . 访问成员函数std::cout << "Leak Memory Address [ " << it.first << "] ";//first是map的第一个参数或者说叫键!void*std::cout << "File [ " << it.second.file << "] ";//second是map的第二个参数或者说叫值!MemInfostd::cout << "Line [ " << it.second.line << "] ";std::cout << "size [ " << it.second.size << "]\n";}std::cout << "--------leak memory info---------\n";}
}void MemCheck::setMemInfo(void* p, const char* file, unsigned long line, unsigned long size){//添加记录!if(!notfreememCheck) {return;}MemInfo pInfo(file, line, size);memcheck._totalMemSize += size;memcheck._memPool[p] = pInfo;
}void MemCheck::deleteMemInfo(void* p){//删除记录if(!notfreememCheck) {return;}auto pInfo = memcheck._memPool.find(p);if(pInfo != memcheck._memPool.end()){memcheck._totalMemSize -= pInfo->second.size;memcheck._memPool.erase(pInfo);}
}void* operator new(size_t size, const char* file, unsigned long line){if(size == 0) size = 1;void* ptr = malloc(size);if(ptr == nullptr){std::cout << "ERR NEWE[]!" << std::endl;}else{//记录MemCheck::setMemInfo(ptr, file, line, size);}return ptr;
}void* operator new[](size_t size, const char* file, unsigned long line){if(size == 0) size = 1;void* ptr = malloc(size);if(ptr == nullptr){std::cout << "ERR NEWE[]!" << std::endl;}else{//记录MemCheck::setMemInfo(ptr, file, line, size);}return ptr;
}//ptr的大小,编译器在new的时候就已经记录在指针前几个字节了!所以不需要告诉他多大
void operator delete(void* ptr){MemCheck::deleteMemInfo(ptr);if(ptr) free(ptr);
}void operator delete[](void* ptr){MemCheck::deleteMemInfo(ptr);if(ptr) free(ptr);
}

main.cpp

#include<iostream>
#include<map>
#include"memcheck.h"using namespace std;
class A{};int main(){A* p = new A;return 0;
}

输出结果:

重点难点:

1.单例模式中的类属性static std::unordered_map<void*, MemInfo> _memPool;和static MemCheck memcheck;在定义时一定要注意其顺序!其保存在静态全局区,释放时以栈的顺序出栈释放,所以必须要将memcheck定义在最后,这样在释放时就优先释放,调用其析构,保证程序的正确执行。如果map被先释放了,再调用析构,那么程序就完全错误了。

2.在memcheck.h中!宏定义了new,所以在main函数中,引入其头文件一定要放在最后,避免对其他文件造成影响。

内存泄漏检测(C++)相关推荐

  1. Unix下C程序内存泄漏检测工具Valgrind安装与使用

    Valgrind是一款用于内存调试.内存泄漏检测以及性能分析的软件开发工具. Valgrind的最初作者是Julian Seward,他于2006年由于在开发Valgrind上的工作获得了第二届Goo ...

  2. OpenCV中的内存泄漏检测

    转自:http://chaishushan.blog.163.com/blog/static/130192897200911685559809/ 内存泄漏时程序开发中经常遇到的问题. 而且出现内存泄漏 ...

  3. JVM内存泄漏检测与处理

    JVM内存泄漏检测与处理(JVM Memory Leak detection and handling) JVM垃圾回收机制的原则和方法 JVM垃圾回收中一个基本原则是对象没有被引用或则引用其它对象, ...

  4. android内存泄漏原因分析,Android Studio3.6的内存泄漏检测功能 VS LeakCanary

    2020年2月,谷歌发布了Android Studio 3.6版.它包括一个新的"内存泄漏检测"功能.这是否意味着我们不再需要流行的内存泄漏检测库"Leak Canary ...

  5. 基于Android Studio的内存泄漏检测与解决全攻略

    自从Google在2013年发布了Android Studio后,Android Studio凭借着自己良好的内存优化,酷炫的UI主题,强大的自动补全提示以及Gradle的编译支持正逐步取代Eclip ...

  6. 内存泄漏检测工具(转载)

    内存泄漏检测工具2007年08月08日 1.     ccmalloc-Linux和Solaris下对C和C++程序的简单的使用内存泄漏和malloc调试库. 2.     Dmalloc-Debug ...

  7. C++ 程序内存泄漏检测方法

    一.前言 在Linux平台上有valgrind可以非常方便的帮助我们定位内存泄漏,因为Linux在开发领域的使用场景大多是跑服务器,再加上它的开源属性,相对而言,处理问题容易形成"统一&qu ...

  8. Valgrind ---内存调试,内存泄漏检测以及性能分析的软件开发工具

    Valgrind是一款用于内存调试.内存泄漏检测以及性能分析的软件开发工具.Valgrind这个名字取自北欧神话中英灵殿的入口. 一般使用方式  valgrind --leak-check=full ...

  9. Visual Studio 内存泄漏检测方法

    Visual Studio 内存泄漏检测方法 非MFC程序可以用以下方法检测内存泄露: 1.程序开始包含如下定义: #ifdef _DEBUG #define DEBUG_CLIENTBLOCK ne ...

  10. C++笔记-构造内存泄漏检测类的基本思路

    目录 基本概念 代码与实例 基本概念 这里主要的思路是,在一个对象在堆区创建后,就把他记录下来,也就是把他记录到某个地方,这个地方负责管理他(和Qt里面的对象树有异曲同工之妙)下面这个例子,把创建的新 ...

最新文章

  1. c语言标准库低通的qsort函数不适宜所有排序任务的原因
  2. 大话设计模式之简单工厂模式
  3. AttributeError: 'PyQt5.QtCore.pyqtSignal' object has no attribute 'connect'
  4. [POI2007]堆积木Klo
  5. JDK1.8 Lambda 使用详解(转)
  6. Mina代码跟踪(1)
  7. 5月19-20日WebRTCon 2018 梳理全球WebRTC技术实践与案例
  8. java什么是网络接口_java接口和类的区别是什么?它们都有哪些作用呢?
  9. linux安装python3.6以后报错处理
  10. 学点数学(3)-函数空间
  11. android中如何通过代码检测是否有root权限?
  12. MYSQL 无重复插入数据更新语法 sql一句话使insert时若主键重复则更新
  13. 3D 空间音效+空气衰减+人声模糊
  14. GeForce RTX 3090驱动下载
  15. 通过WORD精灵在Word中批量添加页码,批量添加或者删除页眉页脚
  16. python控制电脑休眠唤醒键_使用Python实现Wake On Lan远程开机功能
  17. 1117: 零起点学算法24——求正弦和余弦
  18. 新建word 无法切换输入法_为什么word文件中无法切换输入法?
  19. 微信小程序 订单倒计时
  20. listview距离顶端白边

热门文章

  1. 聊一聊SLAP:单一抽象层级原则
  2. Serialize的理解
  3. 关于抓包的一些常用软件
  4. 【ROS Gazebo专题】四、将Fetch机器人放到Gazebo中进行玩耍
  5. 加州大学伯克利分校:MapReduce Spark
  6. MAC的OS系统损坏情况下,U盘启动安装win10系统
  7. 了解和分析iOS Crash Report
  8. 关于访问频次限制的思考
  9. AliTigerTally wtoken算法分析
  10. 开创高质量发展新局面,优炫数据库助推数字中国建设