信息发布→ 登录 注册 退出

C++怎么实现一个简单的内存分析器(Profiler)_C++性能分析与内存Profiler实现

发布时间:2025-11-10

点击量:
答案:通过重载new和delete操作符,结合内存记录、调用堆栈追踪、泄漏报告及线程安全机制,实现轻量级C++内存分析器。

要实现一个简单的 C++ 内存分析器(Memory Profiler),核心思路是拦截程序中的内存分配与释放操作,记录每次分配的大小、调用位置、时间戳等信息,并在程序结束时输出统计结果。通过重载 newdelete 操作符,我们可以轻松捕获所有动态内存操作。

1. 重载 new 和 delete 操作符

C++ 允许全局重载 newdelete,这样就能监控所有通过它们进行的内存操作。我们可以在其中插入日志、计数或堆栈追踪。

示例代码:

#include 
#include 
#include 

// 记录分配地址与大小 std::map allocation_map; size_t total_allocated = 0;

void operator new(size_t size) { void ptr = std::malloc(size); if (ptr) { allocation_map[ptr] = size; total_allocated += size; std::cout << "[ALLOC] " << ptr << " size=" << size << " total=" << total_allocated << "\n"; } return ptr; }

void operator delete(void* ptr) noexcept { if (ptr == nullptr) return; auto it = allocation_map.find(ptr); if (it != allocation_map.end()) { total_allocated -= it->second; std::cout << "[FREE ] " << ptr << " size=" << it->second << " total=" << total_allocated << "\n"; allocation_map.erase(it); } std::free(ptr); }

2. 添加调用堆栈追踪(可选)

为了定位内存泄漏源头,可以加入调用堆栈信息。Linux 下可用 backtrace()backtrace_symbols()

修改后的 new 示例:

#include 

void operator new(size_t size) { void ptr = std::malloc(size); if (ptr) { allocation_map[ptr] = size; total_allocated += size;

    void* call_stack[10];
    int depth = backtrace(call_stack, 10);
    char** symbols = backtrace_symbols(call_stack, depth);

    std::cout << "[ALLOC] " << ptr << " size=" << size << "\n";
    for (int i = 0; i < depth; ++i) {
        std::cout << "  " << symbols[i] << "\n";
    }
    free(symbols);
}
return ptr;

}

编译时需加 -g -rdynamic 参数以保留符号信息。

3. 统计与报告生成

在程序退出时打印未释放的内存块,帮助发现泄漏。

使用 atexit() 注册清理函数:

void report_leaks() {
    std::cout << "\n=== Memory Leak Report ===\n";
    if (allocation_map.empty()) {
        std::cout << "No leaks detected.\n";
    } else {
        for (const auto& pair : allocation_map) {
            std::cout << "[LEAK] " << pair.first 
                       << " size=" << pair.second << "\n";
        }
        std::cout << "Total leaked: " << allocation_map.size() 
                   << " blocks, " << total_allocated << " bytes.\n";
    }
}

// 在 main 中注册 int main() { atexit(report_leaks); // ... your code }

4. 线程安全考虑

多线程环境下,allocation_maptotal_allocated 需要加锁保护。

使用 std::mutex 保证线程安全:

#include 
std::mutex alloc_mutex;

void* operator new(size_t size) { std::lock_guard lock(alloc_mutex); // ... 同上 }

void operator delete(void* ptr) noexcept { std::lock_guard lock(alloc_mutex); // ... 同上 }

基本上就这些。这个简易内存 Profiler 能帮你捕捉分配/释放行为、检测泄漏、统计总量。虽然不如 Valgrind 或 AddressSanitizer 强大,但胜在轻量、可定制,适合嵌入开发流程中做初步排查。

标签:# delete  # 加锁  # 中做  # 时需  # 结束时  # 可选  # 并在  # 帮你  # 就能  # 我们可以  # linux  # 多线程  # 线程  #   # stream  # ios  # c++  # ai  #   
在线客服
服务热线

服务热线

4008888355

微信咨询
二维码
返回顶部
×二维码

截屏,微信识别二维码

打开微信

微信号已复制,请打开微信添加咨询详情!