::operator delete( void * ) 是否知道用 ::operator new( size_t ) 分配的内存大小

Does ::operator delete( void * ) know the size of memory allocated with ::operator new( size_t )

上下文:

我正在尝试创建一个自定义分配器,它在某些方面模仿 std::allocator (不是派生自),但允许实例化分配器。我的通用容器具有构造函数,允许用户指定指向自定义 Allocator 对象的指针。当没有指定分配器时,我希望它默认为从抽象 Allocator class 派生的单例 NewDeleteAllocator。这只是简单地包装了全局 newdelete 运算符。这个想法来自 Pablo Halpern 的 Towards a Better Allocator Model

使用自定义分配器的客户端代码:

// 'foo_container.hpp'

// enclosed in package namespace

template <class T>
class FooContainer
{

private:

    // -- Private member properties --

    Allocator * allocator;

public:

    // -- Constructors --

    FooContainer( Allocator * allocator = 0 )
    {

        this->allocator = !allocator ? (Allocator *)defaultAllocator : allocator;

    }

    FooContainer( const FooContainer &rhs, Allocator * allocator = 0 )
    {

        // don't implicitly copy allocator
        this->allocator = !allocator ? (Allocator *)defaultAllocator : allocator;

        // copying logic goes here

    }

}

自定义分配器实现:

// 'allocator.hpp'

// enclosed in package namespace

class Allocator
{

public:

    virtual ~Allocator(){ };

    virtual void * allocate( size_t bytes ) = 0;
    virtual void deallocate( void * ptr ) = 0;

};

class NewDeleteAllocator : public Allocator
{

public:

    virtual ~NewDeleteAllocator()
    {

    }

    virtual void * allocate( size_t bytes )
    {

        return ::operator new( bytes );

    }

    virtual void deallocate( void * ptr )
    {

        ::operator delete( ptr );    // memory leak?

    }

private:

};

//! @todo Only for testing purposes
const Allocator * defaultAllocator = new NewDeleteAllocator();

主要问题:

我知道通过 new 进行分配可能还会将有关分配的信息与指针一起存储。我意识到使用范围解析运算符 :: 调用 delete 与调用 delete 并不完全相同,但是 ::delete( ptr ) 如何知道 [=25] 的数据大小=] 指的是什么?这是一个安全的操作吗?根据我的理解,根据 C++ 标准,通过 void 指针删除可能会导致未定义的行为。如果这很糟糕,我还能如何实现它?

更多详情:

我用下面的代码做了一些非常粗略的初步测试:

// inside member function of 'FooContainer'

for( size_t i = 0; i < 1000000; i++ )
{

    for( size_t j; j = 1; j < 20; j++ )
    {

        void * ptr = allocator->allocate( j );

        allocator->deallocate( ptr );

    }

}

我使用 Xcode 的分析工具观察了程序的总内存使用情况。内存使用率保持在一个较低的值。我知道这不是检查内存泄漏的正确方法。我不知道编译器是否可以优化它。我只是在试验这个想法。在我对我的图书馆的架构做出任何承诺之前,我非常感谢对主要问题的一些投入。整个方法可能首先存在缺陷。

感谢您的投入。我不想做任何错误的假设。

在调用 ::new 返回的指针上调用 ::delete 是安全的。 在从调用 ::new[] 返回的指针上调用 ::delete[] 是安全的。 如果您不放弃 x 的类型,则在从对 auto x = new {...} 的调用返回的指针上调用 delete x 是安全的。 如果您不放弃 x 的类型,则在从对 auto x = new {...}[z] 的调用返回的指针上调用 delete[] x 是安全的。 混音是UB

"but how does ::delete( ptr ) know the size of the data that ptr is pointing to"

C++中的动态分配内存通常是通过堆来实现的。堆最初分配了非常大量的 space,然后他处理它,让程序处理它的随机块。堆存储它分配的每个内存块的大小。例如,如果你需要 8 个字节的内存,堆至少为你保留 12 个字节,前 4 个字节保存大小,后 8 个字节保存数据。比,它returns一个指向8字节的指针。所以,在删除的过程中,程序通过访问指针知道了多少"to delete" - 4.