84.追踪内存分配的简单方法 in C++
知道你的程序什么时候分配内存,特别是堆内存,是很有用的。弱知道程序在哪里分配内存,便有可能减少它,从而运行更快,因为在堆上分配内存并不是最好的做法,尤其是在性能关键的代码中
此次所探讨,展示的所有东西,都可以很容易的插入到你现有的应用程序中!记住的知识没有应用就是无用的!
🍅追踪内存的方法论
简单例子
#include <iostream>
struct Object {
int x, y, z;
};
int main() {
Object a; //在栈上分配
Object *b = new Object; //在堆上分配
}
在上述可以很明显的知道哪里是栈上分配,哪里是堆上分配,但是如果东西多了起来,如何清楚该程序中有几次堆分配呢?(因为堆分配会拖慢速度)
💡这里的做法是全局重写new
这个操作符
这是new
操作符的new
关键字实际上是一个函数,它被调用时带有特定的大小,可能还有其他参数
(如果如下重写new,则什么也不会发生改变)
这里顺便谈谈size_t
size_t 类型表示C中任何对象所能达到的最大长度,它是无符号整数。
它是为了方便系统之间的移植而定义的,不同的系统上,定义size_t 可能不一样。size_t在32位系统上定义为 unsigned int,也就是32位无符号整型。在64位系统上定义为 unsigned long ,也就是64位无符号整形。size_t 的目的是提供一种可移植的方法来声明与系统中可寻址的内存区域一致的长度。
size_t 在数组下标和内存管理函数之类的地方广泛使用。例如,size_t 用做sizeof 操作符的返回值类型,同时也是很多函数的参数类型,包括malloc 和strlen。
void *operator new(size_t size) {
return malloc(size); //分配适当数量的内存,并返回一个指向该内存的指针
}
通过这段代码,意思是:不要使用标准库中的new操作符,连接器实际上会链接到这个函数中
- 这个函数是返回一个void指针,它只是一个内存地址,因为不想影响程序的行为,故这里便简单输入
return malloc(size)
💡这里重写的好处有很多
-
可以在
operator new
函数中设置一个断点,则程序会在堆分配的地方停下来,便于查找程序中堆分配的语句,从而更好的去优化它们!!! -
也可以在其中输出一点东西来同一的计数
void *operator new(size_t size) { std::cout << "有堆分配!占的内存是:"<< size << "bytes\n"; return malloc(size); }
这样就可以知道每一次堆分配占多少bytes的内存了
同理,delete
也可以重载
void operator delete(void *memory) {
free(memory);
}
如果想知道删除了多少字节的内存,则加参数就可以了
void operator delete(void *memory, size_t size) {
std::cout << "释放了" << size << "bytes\n";
free(memory);
}
而现在利用这两个函数,便可以创建内存分配跟踪器了(写一个结构体),去确切的知道有多少内存被使用,多少内存被分配,多少内存被释放等等,这很有用!
struct MemoryTracker {
uint32_t TotalMemory = 0; //总分配内存
uint32_t TotalFreed = 0; //总释放内存
uint32_t CountMemory() {return TotalMemory - TotalFreed;} //写一个小函数来输出 当前用了多少内存
}
static MemoryTracker temp; //创建一个静态实例,全局的!
void *operator new(size_t size) {
temp.TotalMemory += size; //💡在每一个new里计算总共分配了多少内存
return malloc(size);
}
void operator delete(void *memory, size_t size) {
temp.TotalFreed += size;
free(memory);
}
//可以用一个函数输出我们的内存使用情况
static PrintMemoryUsage() {
std::cout << "内存使用了:" << temp.CountMemory << "\n";
}
由此,利用一个结构体,便可以实现内存的跟踪!
当然可以用VS或者其他工具所提供的内存跟踪,但就个人而言,上面所述的是一个快速且简单的方法,可以看见发生了什么,而它们是绝对有用的,是绝对长期收益的东西。