Search code examples
c++gccclangoperator-overloadingoverload-resolution

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


The following code behaves differently with clang (version 5.0.0-3~16.04.1 on x86_64-pc-linux-gnu) and gcc (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 goes via the overloaded operator delete while clang avoids it preferring the global delete.

(When adding an overloaded operator new both compilers agree and go through both overloaded versions).

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


Solution

  • Compilers are allowed to optimize-out allocations with new and omit calls to the global replaceable operator news and operator deletes completely, even if they have side effects, see [expr.new]/10 and [expr.delete]/7.1 of the C++17 standard draft.


    If you compile without the -O2 flag, you will see your message printed with both compilers and gcc trunk also omits the allocation with optimizations enabled.


    If the allocation/deallocation function calls are not removed by the compiler, I would assume that your operator delete has undefined behavior, because you have no guarantee that the pointer you are being passed was allocated by malloc and calling free on it has undefined behavior if it wasn't.

    You need to always replace both operator new and operator delete.