C++极简内存泄露检测工具(34行代码实现)

工具特点

1 极度简单:34行代码实现,线程安全

2 入寝式检测:需要给现有重点怀疑的类添加一行入寝代码

3 只针对类类型:动态数组需要使用更为复杂的技术,不在检测能力范围之内。考虑到大部分C++代码都以类实现代码,所以我认为这已经足够。

4 仅限于测试:不可以用于正式代码。当我们发现有可能有内存泄露的时候,使用该工具入侵到当前代码。跑一段时间发现有没有内存泄露。发现泄露之后需要再次删除入侵代码。

实现原理

给类添加一个静态成员,这个成员在类对象复制控制的时候记录该对象创建(构造)了多少次,释放(析构)了多少次。

在程序退出时向控制台输出统计结果。

代码非常易于理解。

一些特殊的场景

1 服务端程序:服务端程序往往长时间运行不退出。但是我们的工具只有程序正确的退出才会给出统计结果。所以,你的服务端程序必须要能够(改造成)正常退出(可以使用Web接口,捕获信号,接受输入等方式)。

2 动态数组检测:如果历史代码里有大量的动态数组,使用原始指针来访问管理。那么这种情况下,该工具爱莫能助。我们认为这样的C++代码首先是不合理的。所以也不予支持。

程序效果

1 可靠:由于代码过于简单,所以库本身不会有问题。经历过多个产品的内存泄露检测工作。完美可信赖。

2 好用:只需要包含一个头文件即可。

具体实现

代码下载

1 Gitee

CalmReason/cxx_memory_leak_check

2 百度云

链接:https://pan.baidu.com/s/1x4d2K4ZdoS9XdJrzyb311A

提取码:1234

源代码

memory_leak_checker.hpp

只需要把这个头文件包含到你的工程里就可以使用:

#ifndef MEMORY_LEAK_CHECKER_H
#define MEMORY_LEAK_CHECKER_H

//memory checke library begin
#include <assert.h>
#include <iostream>
#include <atomic>
#include <string>
class object_usage_counter {
public:
    object_usage_counter(const char* name) :m_name(name), m_counter(0) {};
    ~object_usage_counter() { std::cout << "class " << m_name << " memory leak num = " << m_counter << std::endl; };
    void inc() { ++m_counter; }
    void dec() { --m_counter;	assert(m_counter >= 0); }
private:
    std::atomic<long long> m_counter;
    std::string m_name;
};
template<typename T>
class counter_by_copy {
public:
    counter_by_copy() { m_the_only_object_for_one_class.inc(); }
    ~counter_by_copy() { m_the_only_object_for_one_class.dec(); }
    counter_by_copy(const counter_by_copy&) { m_the_only_object_for_one_class.inc(); }
private:
    //the only object to count usage.
    static object_usage_counter m_the_only_object_for_one_class;
};
//TIPS:template class's static member object can be define at the .h file
template<typename T>
object_usage_counter counter_by_copy<T>::m_the_only_object_for_one_class(typeid(T).name());
//memory checke library end

#endif // !MEMORY_LEAK_CHECKER_H


//example usage
/*
class A
{
public:
    //A's copy control member functions call counter increasing or decreasing usage.
    counter_by_copy<A> m_checker;
};
*/

测试程序 test_main.cpp

#include "memory_leak_checker.hpp"
#include <memory>
#include <vector>
#include <thread>
#include <future>

class A
{
public:
	counter_by_copy<A> m_checker;
};

A* CreateA(void)
{
	return new A;
}

void f(void)
{
	auto p = new A;
	//do some thing

	//这里泄漏了一次
}

int main(int argc, char* argv[])
{
	auto pa = new A;//leak 1
	new A[5];//leak 5

	auto p2 = CreateA();
	delete p2;

	f();//leak 1

	auto listA = std::vector<std::shared_ptr<A>>(5, std::make_shared<A>());//no leak
	for (int i = 0; i < 3; ++i)
	{
		listA.push_back(std::make_shared<A>());//no leak
	}
	std::cout << "test leack 7" << std::endl;
}

运行输出

test leack 7

class 1A memory leak num = 7

CMake工程文件 CMakeLists.txt

如果你需要跑测试用例,可以用这个CMakeLists.txt文件,也可以自己拷贝代码自己创建工程使用。

cmake_minimum_required(VERSION 3.3)
project(memory_leak_check)
add_executable(main test_main.cpp)

竞品分析

1 VS自带的Debug Report

我用过VS自带内存泄露诊断工具Debug。这个工具有些场景是发现不了的。过于简单。

而且只能用VS调试环境运行。无法在Release环境运行。

2 Valgrind

这个工具做的事情太多了,太复杂了。什么场景都想把控。结果就是乱七八糟给你一堆报告,有没有泄露你也不敢信。报告内容太多,多的你都不知道到底泄露了没有。

关键是你不知道它靠不靠谱。

2.1 A Cross-Platform Memory Leak Detector (dcweb.cn)

3 对比分析

当前工具主打一个简单,主打一个可控,主打一个准确无误。

keep it stupid simple !

以上。

最后

如果有任何问题,欢迎随时与我交流。

可以留言或者私信交流。

祝你工作顺利!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Visual Leak Detector是一款免费的、健全的、开源的Visual C++内存泄露检测系统。相比Visual C++自带的内存检测机制,Visual Leak Detector可以显示导致内存泄露的完整内存分配调用堆栈。 下载Visual Leak Detector,当前版本2.2.3,在Visual C++ IDE的"工具"→"选项"→"项目和解决方案"→"VC++ 目录","包含文件"增加VLD的"\include"路径,"库文件"增加VLD的"\lib\Win32"路径,另外动态库"\bin\Win32"路径在安装时已经添加到环境变量里面了,若是未添加,则需要手动拷贝"\bin\Win32"下的文件到工程Debug目录。下 展开查看详细 收起信息 返回顶部 1.新建一个Win32控制台项目; 2.添加代码如下所示: #include "stdafx.h" #include "vld.h" int _tmain(int argc, _TCHAR* argv[]) { char *pBuf = new char[200]; return 0; } 3.在Debug模式下的“输出”窗口,将有如下信息: 报告列出了内存泄露是在第几块,所在的地址,泄露的字节,调用的堆栈,内存内容。双击调用堆栈可以跳转到所在。 4.在Release模式下,不会链接Visual Leak Detector。 5.Visual Leak Detector有一些配置项,可以设置内存泄露报告的保存地(文件、调试器),拷贝"\Visual Leak Detector"路径下的vld.ini文件到工程的Debug目录下(在IDE运的话,则需要拷贝到工程目录下),修改以下项: ReportFile = .\memory_leak_report.txt ReportTo = both 直接双击Debug目录下exe,文件内容跟“输出”窗口的内容一样。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C++程序员Carea

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值