You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基准测试场景下g++编译内存统计结果与MSVC不一致问题

故障根因
  • 你仅重载了C++14标准才新增的带size_t参数的sized operator delete,没有重载C++标准中最基础的无size参数的operator delete
  • MSVC默认启用了高版本C++标准支持,调用delete时会优先匹配你写的带size参数的重载,所以统计逻辑正常运行
  • GCC/Clang默认没有开启sized deallocation特性(或默认使用旧版C++标准),调用delete时会走系统默认的无size参数operator delete,你没有重载该版本,导致内存释放的统计完全失效,totalFree数值不会累加,才会出现内存占用逐轮测试持续上涨的异常现象
修复步骤

1. 补充指针分配大小记录逻辑

修改AllocationMetrics结构体,增加映射表存储每个分配指针对应的内存大小,同时加锁保证多线程安全:

#include <unordered_map>
#include <mutex>

struct AllocationMetrics {
    uint64_t totalMemory = 0;
    uint64_t totalFree = 0;
    uint64_t maxMem = 0;
    std::unordered_map<void*, size_t> allocMap;
    std::mutex mtx;

    uint64_t getCurrentUsage() { 
        std::lock_guard<std::mutex> lock(mtx);
        return totalMemory - totalFree; 
    }

    void setMaxMem() {
        std::lock_guard<std::mutex> lock(mtx);
        uint64_t temp = getCurrentUsage();
        if (temp > maxMem)
            maxMem = temp;
    }

    void resetMaxMem() { 
        std::lock_guard<std::mutex> lock(mtx);
        maxMem = 0; 
    }
};

2. 重载所有版本的new/delete运算符

覆盖所有可能的内存分配释放入口,包括数组版本:

AllocationMetrics s_allocationMetrics;

void* operator new(size_t size) {
    void* ptr = malloc(size);
    std::lock_guard<std::mutex> lock(s_allocationMetrics.mtx);
    s_allocationMetrics.totalMemory += size;
    s_allocationMetrics.allocMap[ptr] = size;
    return ptr;
}

void* operator new[](size_t size) {
    return operator new(size);
}

void operator delete(void* ptr) noexcept {
    std::lock_guard<std::mutex> lock(s_allocationMetrics.mtx);
    auto it = s_allocationMetrics.allocMap.find(ptr);
    if (it != s_allocationMetrics.allocMap.end()) {
        s_allocationMetrics.totalFree += it->second;
        s_allocationMetrics.allocMap.erase(it);
    }
    free(ptr);
}

void operator delete(void* ptr, size_t size) noexcept {
    std::lock_guard<std::mutex> lock(s_allocationMetrics.mtx);
    s_allocationMetrics.totalFree += size;
    s_allocationMetrics.allocMap.erase(ptr);
    free(ptr);
}

void operator delete[](void* ptr) noexcept {
    operator delete(ptr);
}

void operator delete[](void* ptr, size_t size) noexcept {
    operator delete(ptr, size);
}

3. 编译时指定C++标准

编译命令增加-std=c++17参数,避免不同编译器默认标准差异导致的兼容问题:

g++ Source.cpp Functions.cpp benchmarking.cpp -std=c++17 -O2
额外注意事项
  • 如果程序使用了自定义分配器、或者直接调用malloc/free分配释放内存,这部分内存不会被new/delete的重载统计到,需要单独处理
  • 单线程场景下可以去掉锁逻辑提升性能,多线程环境必须加锁避免统计错误和容器崩溃

内容的提问来源于stack exchange,提问作者Aleksander Markovskyy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 22:45:03