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

重载delete[]运算符实现内存追踪时的失效问题

解决全局重载delete[]未生效的问题

问题根源在于:针对内置类型数组的delete[]操作,编译器会调用不带std::size_t参数的全局operator delete[]版本,而你只重载了带size参数的版本,导致自定义逻辑未被触发。

在C++标准中,全局operator delete[]存在两个重载:

  • void operator delete[](void* ptr) noexcept;
  • void operator delete[](void* ptr, std::size_t size) noexcept;

销毁内置类型(如int)数组时,编译器不会传递size参数,只会调用第一个不带size的版本;只有销毁自定义类型数组时,才会触发带size的重载。


修改后的完整代码

#include<iostream>
#include<new> // 引入std::bad_alloc

// 全局内存追踪变量
std::size_t g_allocatedMemory{};

// =======================================================================
// 标量版new重载
void* operator new(std::size_t size)
{
    g_allocatedMemory += size;
    
    std::cout << "Allocating " << size << " bytes\n";
    std::cout << "Current allocation = " << g_allocatedMemory << " bytes\n\n";

    void* ptr = malloc(size);
    if (!ptr) {
        throw std::bad_alloc(); // 符合标准new的异常抛出行为
    }
    return ptr;
}

// 标量版delete重载(带size)
void operator delete(void* memory, std::size_t size) noexcept
{
    g_allocatedMemory -= size;

    std::cout << "Freeing " << size << " bytes\n";
    std::cout << "Current allocation = " << g_allocatedMemory << " bytes\n\n";
    
    free(memory);
}

// 补充标量版delete重载(不带size,处理内置类型销毁)
void operator delete(void* memory) noexcept
{
    std::cout << "Freeing (unknown size)\n";
    free(memory);
}

// =======================================================================
// 数组版new[]重载
void* operator new[](std::size_t size)
{
    g_allocatedMemory += size;
    
    std::cout << "Allocating " << size << " bytes (array)\n";
    std::cout << "Current allocation = " << g_allocatedMemory << " bytes\n\n";

    void* ptr = malloc(size);
    if (!ptr) {
        throw std::bad_alloc();
    }
    return ptr;
}

// 补充数组版delete[]重载(不带size,处理内置类型数组销毁)
void operator delete[](void* memory) noexcept
{
    std::cout << "Freeing array (unknown size)\n";
    free(memory);
}

// 数组版delete[]重载(带size,处理自定义类型数组销毁)
void operator delete[](void* memory, std::size_t size) noexcept
{    
    g_allocatedMemory -= size;

    std::cout << "Freeing " << size << " bytes (array)\n";
    std::cout << "Current allocation = " << g_allocatedMemory << " bytes\n\n";
    
    free(memory);
}

// =======================================================================

int main()
{
    // 测试内置类型数组
    int* p{ new int[5] };
    delete[] p;

    // 测试自定义类型数组(会触发带size的delete[])
    struct Test {};
    Test* t{ new Test[3] };
    delete[] t;

    return 0;
}

关键修改说明

  1. 补充无参数的delete/delete[]重载:覆盖内置类型的销毁场景,确保所有释放操作都能触发自定义逻辑。
  2. 添加异常抛出逻辑:在new/new[]中分配失败时抛出std::bad_alloc,符合C++标准行为。
  3. 添加noexcept修饰:所有delete/delete[]重载加上noexcept,匹配标准签名要求。
  4. 区分日志输出:标量和数组操作的日志做了区分,便于调试时快速定位。

运行修改后的代码,delete[] p(int数组)会调用无参数的operator delete[],自定义类型数组的销毁则会触发带size的重载,两种场景都能正常追踪内存变化。

内容的提问来源于stack exchange,提问作者m-salman-05

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 08:56:08