C++跟踪内存分配
重写 new 和 delete 操作符
我们知道一个 class 的 new 是分为三步:operator new
(其内部调用 malloc)返回 void*
、static_cast
转换为这个对象指针、构造函数。而 delete
则分为两步:构造函数、operator delete
。
new 和 delete 都是表达式,是不能重载的;而把他们行为往下分解则是有 operator new 和 operator delete,是有区别的。
直接用的表达式的行为是不能变的,不能重载的,即 new 分解成上图的三步与 delete 分解成上图的两步是不能重载的。这里内部的 operator new 和 operator delete 底层其实是调用的 malloc,这些内部的几步则是可以重载的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
// 写这个函数就是说不要用standard library的operator new
// 链接器实际上就会改为链接这个函数
void* operator new(size_t size)
{
std::cout << "Allocing " << size << " bytes\n";
return malloc(size);
}
void operator delete(void* memory, size_t size)
{
std::cout << "Free " << size << " bytes\n";
free(memory);
}
struct Entity
{
int x, y, z;
};
int main()
{
{
std::string name = "hbh";
}
Entity* e = new Entity();
delete e;
std::cin.get();
}
还可以写一个简单统计内存分配的类,在每次 new 的时候统计分配内存,在每次 delete 时统计释放内存,可计算出已经分配的总内存:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// 重写new、free操作符之后就能方便地跟踪内存分配了(加断点)
#include <iostream>
#include <memory>
struct AllocationMetrics
{
uint32_t TotalAllocated = 0; //总分配内存
uint32_t TotalFreed = 0; //总释放内存
uint32_t CurrentUsage() { return TotalAllocated - TotalFreed; } //写一个小函数来输出 当前用了多少内存
};
static AllocationMetrics s_AllocationMetrics; //创建一个全局静态实例
void *operator new(size_t size)
{
s_AllocationMetrics.TotalAllocated += size; //在每一个new里计算总共分配了多少内存
// std::cout << "Allocate " << size << " bytes.\n";
return malloc(size);
}
void operator delete(void *memory, size_t size)
{
s_AllocationMetrics.TotalFreed += size;
// std::cout << "Free " << size << " bytes.\n";
free(memory);
}
struct Object
{
int x, y, z;
};
//可以用一个函数输出我们的内存使用情况
static void PrintMemoryUsage()
{
std::cout << "Memory Usage:" << s_AllocationMetrics.CurrentUsage() << " bytes\n";
}
int main()
{
PrintMemoryUsage();
{
std::unique_ptr<Object> obj = std::make_unique<Object>();
PrintMemoryUsage();
}
PrintMemoryUsage();
Object *obj = new Object;
PrintMemoryUsage();
delete obj;
PrintMemoryUsage();
std::string string = "Cherno";
PrintMemoryUsage();
return 0;
}
本文由作者按照 CC BY 4.0 进行授权