Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
174 views
in Technique[技术] by (71.8m points)

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

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 can either be constructed directly onto the pool, or it can use the pool for dynamic memory calls or it could in theory do both. I would like to be able to overload operator new and operator delete in a way that would call my pools "alloc()" and "free()" functions in order to get the memory needed for the object to construct upon.

One of the main issues that I am having is getting my operator delete to be able to free up the memory by calling the pool->free() function I have written. I came up with a hack that fixes it by passing the pool into the constructor and having the destructor do the deallocation work. This is all fine and dandy until someone needs to inherit from this class and override the destructor for their own needs and then forgets to do the memory deallocations. Which is why i want to wrap it all up in the operators so the functionality is tucked away and inherited by default.

My Code Is on GitHub here: https://github.com/zyvitski/Pool

My class definition for the Client is as follows:

class Client
{
public:
    Client();
    Client(Pool* pool);
    ~Client();

    void* operator new(size_t size,Pool* pool);
    void operator delete(void* memory);

    Pool* m_pPool;
};

And the implementation is:

Client::Client()
{

}
Client::Client(Pool* pool)
{
    m_pPool = pool;
}
Client::~Client()
{
    void* p = (void*)this;
    m_pPool->Free(&p);
    m_pPool=nullptr;
}
void* Client::operator new(size_t size, Pool* pool)
{
    if (pool!=nullptr) {
        //use pool allocator
        MemoryBlock** memory=nullptr;
        memory = pool->Alloc(size);
       return *memory;
    }
    else throw new std::bad_alloc;
}
void Client::operator delete(void* memory)
{
    //should somehow free up the memory back to the pool
    // the proper call will be:
    //pool->free(memory);
    //where memory is the address that the pool returned in operator new

}

Here is the example Main() that i'm using for the moment:

int main(int argc, const char * argv[]){
    Pool* pool = new Pool();
    Client* c = new(pool) Client(pool);
    /*
    I'm using a parameter within operator new to pass the pool in for use and i'm also passing the pool as a constructor parameter so i can free up the memory in the destructor
    */

    delete c;
    delete pool;
    return 0;
}

So far my code works, but I want to know if there is a better way to achieve this? Please let me know if anything I am asking/doing is simply impossible, bad practice or just simply dumb. I am on a MacBook Pro right now but i would like to keep my code cross platform if at all possible.

If you have any questions that would help you help me do let me know.

And of course, Thanks in advance to anyone who can help.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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 << '
';
    header->pool = &pool;
    return header + 1;
}

void Client::operator delete(void* memory)
{
    auto header = static_cast<MemoryHeader*>(memory) - 1;
    std::cout << " Delete Header: " << header << '
';
    header->pool->Dealloc(header);
}

int main()
{
    Pool pool;
    Client* p = new(pool) Client;
    std::cout << "Client Pointer: " << p << '
';
    delete p;
    return 0;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...