在不重载 new 的情况下重载 operator delete 时正确的行为是什么? gcc 和 clang 不同

What's the right behavior when overloading operator delete without overloading new? gcc and clang differ

以下代码与 clang(x86_64-pc-linux-gnu 上的版本 5.0.0-3~16.04.1)和 gcc[=29 的行为不同=] (9.2.0).

void operator delete(void* ptr) noexcept {
    std::cout << "overloaded delete" << std::endl;
    free(ptr);
}

int main() {
    int* pint = new int;
    delete pint; // clang doesn't go through overloaded operator delete, gcc does
}

gcc 通过重载 operator deleteclang 避免它更喜欢 global delete.

(添加重载 operator new 时,两个编译器都同意并通过两个重载版本)。

代码:http://coliru.stacked-crooked.com/a/0903bd53a8c04a9b

编译器可以使用 new 优化分配并完全忽略对全局可替换 operator news 和 operator deletes 的调用,即使它们有副作用,参见 [expr.new]/10 and [expr.delete]/7.1 的 C++17 标准草案。


如果您在没有 -O2 标志的情况下进行编译,您将看到您的消息与两个编译器一起打印,并且 gcc trunk 也会在启用优化的情况下省略分配。


如果 allocation/deallocation 函数调用没有被编译器删除,我会假设你的 operator delete 有未定义的行为,因为你不能保证你传递的指针是由malloc 并在其上调用 free 如果不是,则具有未定义的行为。

您需要始终替换 operator newoperator delete