Using operator new and operator delete with a custom memory pool/allocator

后端 未结 3 1921
春和景丽
春和景丽 2020-12-07 03:13

I\'m working on a memory pool/memory allocator implementation and I am setting it up in a manor where only a special \"Client\" object type can draw from the pool.The client

相关标签:
3条回答
  • 2020-12-07 03:28

    With the help of Dieter Lücking I was able to figure out how to use my pool in operator new and operator delete

    Here is the code for operator new:

    void* ObjectBase::operator new(size_t size, Pool* pool)
    {
        if (pool!=nullptr) {
            //use pool allocation
            MemoryBlock** block = pool->Alloc(size+(sizeof(MemoryHeader)));
            MemoryBlock* t = * block;
            t = (MemoryBlock*)((unsigned char*)t+sizeof(MemoryHeader));
            MemoryHeader* header = new(*block)MemoryHeader(pool);
            header=nullptr;
            return t;
        }
        else{
            //use std allocation
            void* temp = ::operator new(size);
            if (temp!=nullptr) {
                return temp;
            }
            else throw new std::bad_alloc;
        }
    }
    

    Here is the code for operator delete

    void ObjectBase::operator delete(void* memory)
    {
        MemoryBlock* temp = (MemoryBlock*)((unsigned char*)memory-sizeof(MemoryHeader));
        MemoryHeader* header = static_cast<MemoryHeader*>(temp);
        if (header->pool!=nullptr) {
            if (header->pool->Free((MemoryBlock**)&header));
            else
            {
                ::operator delete(memory);
            }
        }
        else{
            ::operator delete(memory);
        }
    }
    

    I'm using the "Memory Header" idea that was suggested.

    The code is also set up in a way that defaults to using a standard memory allocation call if for some reason the pool fails.

    Thanks Again for your help.

    0 讨论(0)
  • 2020-12-07 03:31

    You might store additional information just before the returned memory address

    #include <iostream>
    #include <type_traits>
    
    class Pool {
    public:
        static void* Alloc(std::size_t size) { return data; }
        static void Dealloc(void*) {}
    private:
        static char data[1024];
    };
    char Pool::data[1024];
    
    
    class Client
    {
    public:
        void* operator new(size_t size, Pool& pool);
        void operator delete(void* memory);
    };
    
    
    struct MemoryHeader {
        Pool* pool;
    };
    
    
    void* Client::operator new(size_t size, Pool& pool)
    {
        auto header = static_cast<MemoryHeader*>(pool.Alloc(sizeof(MemoryHeader) + size));
        std::cout << "    New Header: " << header << '\n';
        header->pool = &pool;
        return header + 1;
    }
    
    void Client::operator delete(void* memory)
    {
        auto header = static_cast<MemoryHeader*>(memory) - 1;
        std::cout << " Delete Header: " << header << '\n';
        header->pool->Dealloc(header);
    }
    
    int main()
    {
        Pool pool;
        Client* p = new(pool) Client;
        std::cout << "Client Pointer: " << p << '\n';
        delete p;
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-07 03:39

    If your delete operator simply calls free, you custom allocator will not do e very good job. The idea of a custom allocator is that it will work with a predefined memory region which it will have control over: when it allocates memory it will be from it's memory region or pool and when the memory is freed, the allocator is 'informed' it can reuse that memory. Now, if you use free, you just return the memory to the heap, not to your memory pool. The way this part is usually done is with the use of smart pointers - to keep track of what memory is available.

    Any other mechanism will do as long as you can keep track of which addresses are in use and which are available.

    Hope this helps

    0 讨论(0)
提交回复
热议问题