重载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; }
关键修改说明
- 补充无参数的delete/delete[]重载:覆盖内置类型的销毁场景,确保所有释放操作都能触发自定义逻辑。
- 添加异常抛出逻辑:在
new/new[]中分配失败时抛出std::bad_alloc,符合C++标准行为。 - 添加noexcept修饰:所有
delete/delete[]重载加上noexcept,匹配标准签名要求。 - 区分日志输出:标量和数组操作的日志做了区分,便于调试时快速定位。
运行修改后的代码,delete[] p(int数组)会调用无参数的operator delete[],自定义类型数组的销毁则会触发带size的重载,两种场景都能正常追踪内存变化。
内容的提问来源于stack exchange,提问作者m-salman-05
相关产品推荐
相关产品推荐

