自定义operator delete释放malloc内存的指针是否合法?GCC警告是bug吗?
这是不是GCC的bug?
我通过std::malloc分配内存,用placement new构造String类对象,同时为String声明了自定义operator delete,其内部调用std::free释放内存。已知删除非new分配的指针通常非法,但我这个场景是自定义delete适配malloc的情况,代码如下:
#include <memory> #include <cstdlib> #include <utility> class String{ public: /*virtual*/ ~String(){} static void operator delete(void* p) noexcept; }; void foo(size_t extraSize){ if(void* mem = std::malloc(sizeof(String) + extraSize)){ String* p = new(mem) String; delete p; } } // 该函数定义在其他*.cpp文件中 /* void String::operator delete(void* p) noexcept{ std::free(p); } */
用x86-64 GCC 13.2编译后出现如下警告:
<source>: In function 'void foo(size_t)': <source>:14:16: warning: 'static void String::operator delete(void*)' called on pointer returned from a mismatched allocation function [-Wmismatched-new-delete] 14 | delete p; | ^ <source>:12:31: note: returned from 'void* malloc(size_t)' 12 | if(void* mem = std::malloc(sizeof(String) + extraSize)){ | ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~ Compiler returned: 0
执行以下任一操作可消除警告:
- 不开启优化编译(移除
-O编译选项) - 在当前翻译单元中定义
String::operator delete(void* p)(取消注释最后几行)
结论:这不是GCC的bug
原因在于:
- 当自定义
operator delete仅在当前翻译单元声明、未提供定义时,GCC在优化模式下无法知晓该函数的实际实现逻辑,只能依据C++默认的内存分配/释放配对规则(new对应delete,malloc对应free)进行诊断,因此触发了不匹配的警告。 - 当在当前翻译单元提供
operator delete的定义后,编译器能明确看到函数内部调用了std::free,确认这个释放操作和malloc的分配是适配的,所以不会再触发警告。 - 关闭优化时,编译器的静态分析强度降低,没有执行这个配对检查,因此警告消失。
这个警告是编译器的合理诊断行为,目的是防止开发者误将常规delete用于malloc分配的内存(无自定义delete适配的场景),并非编译器bug。
内容的提问来源于stack exchange,提问作者Cooler
相关产品推荐
相关产品推荐

