重载新的数组运算符有多安全?
How safe is overloading new array operator?
假设我正在使用一个在堆上分配的结构并用作
- 新建[]和删除[]
- shared_ptr(新[])
那么我可以简单地重载它的新数组运算符并且不触及任何删除 [] 运算符
struct alignas(256) MyStruct
{
Item i1,i2;
void * operator new[](unsigned long int size)
{
return aligned_alloc(256,size);
}
void * operator new (unsigned long int size)
{
return aligned_alloc(256,size);
}
};
并认为它没有任何泄漏就完成了吗?
GCC 6.3 和 c++0x。
如果您在一个对象上重载 new
,您也应该重载 delete
。同样,如果您重载 new[]
,您应该重载 delete[]
。这是因为该对象将使用默认值 delete
,这可能会导致崩溃,具体取决于您对 new
.
的处理方式
根据您的编译器,delete
可能会调用 free()
,但是您应该养成同时重载 new
和 delete
的习惯,尤其是当您更改你的对象是如何分配的。
事实上,无法保证您的标准库如何实现这些 operator new()
函数。您的标准实现可能只是调用 malloc()
和 free()
,但这不是必须的。它也可以使用 sbreak()
系统调用本身来支持它管理的内存对象。或者它可以使用 mmap()
系统调用。
这三个中的任何一个都是完全可行的,并且与其他两个实现不兼容。而且,同样糟糕的是,您的标准 operator delete()
实现可能会查询您传递给它的指针前面的一些隐藏数据字段以执行其内部簿记。 如果传递给您的标准的指针operator delete()
实际上不是匹配 operator new()
返回的指针,您有未定义的行为。而且真的很糟糕的事情发生的概率非常高。
真的没办法:如果你提供operator new()
,你还必须提供operator delete()
。否则,一切都可能崩溃。
假设我正在使用一个在堆上分配的结构并用作
- 新建[]和删除[]
- shared_ptr(新[])
那么我可以简单地重载它的新数组运算符并且不触及任何删除 [] 运算符
struct alignas(256) MyStruct
{
Item i1,i2;
void * operator new[](unsigned long int size)
{
return aligned_alloc(256,size);
}
void * operator new (unsigned long int size)
{
return aligned_alloc(256,size);
}
};
并认为它没有任何泄漏就完成了吗?
GCC 6.3 和 c++0x。
如果您在一个对象上重载 new
,您也应该重载 delete
。同样,如果您重载 new[]
,您应该重载 delete[]
。这是因为该对象将使用默认值 delete
,这可能会导致崩溃,具体取决于您对 new
.
根据您的编译器,delete
可能会调用 free()
,但是您应该养成同时重载 new
和 delete
的习惯,尤其是当您更改你的对象是如何分配的。
事实上,无法保证您的标准库如何实现这些 operator new()
函数。您的标准实现可能只是调用 malloc()
和 free()
,但这不是必须的。它也可以使用 sbreak()
系统调用本身来支持它管理的内存对象。或者它可以使用 mmap()
系统调用。
这三个中的任何一个都是完全可行的,并且与其他两个实现不兼容。而且,同样糟糕的是,您的标准 operator delete()
实现可能会查询您传递给它的指针前面的一些隐藏数据字段以执行其内部簿记。 如果传递给您的标准的指针operator delete()
实际上不是匹配 operator new()
返回的指针,您有未定义的行为。而且真的很糟糕的事情发生的概率非常高。
真的没办法:如果你提供operator new()
,你还必须提供operator delete()
。否则,一切都可能崩溃。