自定义内存分配和统计
2024/8/7大约 2 分钟

CppUpgrade
仓库地址
为了方便说明,对int进行简单封装,其定义如下:
class Int {
public:
int value;
};本文实现内存统计的思路是:
在每次申请内存时,在真正所需内存的开头额外申请一块内存,存储当前内存块的信息,如大小、类型等。
对应的,在内存释放时需要同时释放额外申请的内存。
0.传统new的执行过程
new Int()
|
|-operator new()
| |
| --malloc()
|
--Int()1.对底层内存分配、内存释放函数进行封装
namespace qstx {
static std::atomic<size_t> total_memory = 0;
struct header
{
size_t size = 0;
const char* type = nullptr;
};
void* m_malloc(size_t size, const char* type)
{
void* header_ptr = malloc(sizeof(header) + size);
header* tmp_header = static_cast<header*>(header_ptr);
tmp_header->size = size;
tmp_header->type = type;
total_memory += size;
return (unsigned char*)header_ptr + sizeof(header);
}
void m_free(void* ptr)
{
void* header_ptr = (unsigned char*)ptr - sizeof(header);
total_memory -= static_cast<header*>(header_ptr)->size;
free(header_ptr);
}
}2.重写类的new、delete函数
static void* operator new(size_t size)
{
return qstx::m_malloc(size, typeid(Int).name());
}
static void* operator new[](size_t size)
{
return qstx::m_malloc(size, typeid(Int).name());
}
static void operator delete(void* ptr)
{
qstx::m_free(ptr);
}
static void operator delete[](void* ptr)
{
qstx::m_free(ptr);
}3.验证
通过new、delete构造和销毁对象,输出使用的总内存进行验证
int main()
{
{
Int* p = new Int();
std::cout << "Int value: " << p->value << std::endl;
std::cout << "Memory Used: " << qstx::total_memory << "Bytes" << std::endl;
delete p;
}
std::cout << "Memory Used: " << qstx::total_memory << "Bytes" << std::endl;
std::cout << std::endl;
{
Int* p_array = new Int[3];
for (int i = 0; i < 3; ++i) {
p_array[i].value = i;
std::cout << "Int value: " << p_array[i].value << std::endl;
std::cout << "Memory Used: " << qstx::total_memory << "Bytes" << std::endl;
}
delete[] p_array;
}
std::cout << "Memory Used: " << qstx::total_memory << "Bytes" << std::endl;
}上述代码的输出如下:
Int value: 0
Memory Used: 4Bytes
Memory Used: 0Bytes
Int value: 0
Memory Used: 12Bytes
Int value: 1
Memory Used: 12Bytes
Int value: 2
Memory Used: 12Bytes
Memory Used: 0Bytes4.改进
直接定义一个宏,在类中批量重载new、delete函数
#define DEFINE_CLASS_MEMORY_ALLOCATOR(type) \
static void* operator new(size_t size) { \
return qstx::m_malloc(size, typeid(type).name()); \
} \
static void* operator new[](size_t size) { \
return qstx::m_malloc(size, typeid(type).name()); \
} \
static void operator delete(void* ptr) { \
qstx::m_free(ptr); \
} \
static void operator delete[](void* ptr) { \
qstx::m_free(ptr); \
}
class Int {
public:
DEFINE_CLASS_MEMORY_ALLOCATOR(Int)
//Other Codes
};