工具特点
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 !
以上。
最后
如果有任何问题,欢迎随时与我交流。
可以留言或者私信交流。
祝你工作顺利!