在不重载 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 delete
而 clang 避免它更喜欢 global delete
.
(添加重载 operator new
时,两个编译器都同意并通过两个重载版本)。
编译器可以使用 new
优化分配并完全忽略对全局可替换 operator new
s 和 operator delete
s 的调用,即使它们有副作用,参见 [expr.new]/10 and [expr.delete]/7.1 的 C++17 标准草案。
如果您在没有 -O2
标志的情况下进行编译,您将看到您的消息与两个编译器一起打印,并且 gcc trunk 也会在启用优化的情况下省略分配。
如果 allocation/deallocation 函数调用没有被编译器删除,我会假设你的 operator delete
有未定义的行为,因为你不能保证你传递的指针是由malloc
并在其上调用 free
如果不是,则具有未定义的行为。
您需要始终替换 operator new
和 operator delete
。
以下代码与 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 delete
而 clang 避免它更喜欢 global delete
.
(添加重载 operator new
时,两个编译器都同意并通过两个重载版本)。
编译器可以使用 new
优化分配并完全忽略对全局可替换 operator new
s 和 operator delete
s 的调用,即使它们有副作用,参见 [expr.new]/10 and [expr.delete]/7.1 的 C++17 标准草案。
如果您在没有 -O2
标志的情况下进行编译,您将看到您的消息与两个编译器一起打印,并且 gcc trunk 也会在启用优化的情况下省略分配。
如果 allocation/deallocation 函数调用没有被编译器删除,我会假设你的 operator delete
有未定义的行为,因为你不能保证你传递的指针是由malloc
并在其上调用 free
如果不是,则具有未定义的行为。
您需要始终替换 operator new
和 operator delete
。