Custom memory alloc and dealloc which multiple Inheritance class

人走茶凉 提交于 2019-12-29 06:44:17

问题


i want do memory management in my project. i do not want operator global new/delete so i implement a simple memory alloctor. this is my code:

class IAllocator
{
public:
    void* Alloc( unsigned int size )
    {
        1. alloc memory.
        2. trace alloc.
    }
    void Dealloc( void* ptr )
    {
        1. free memory.
        2. erase trace info.
    }
    template< typename T >
    void Destructor( T* ptr )
    {
        if ( ptr )
            ptr->~T();
    }
};
// macro for use easy.
# define MYNEW( T ) new ( g_Allocator->Alloc( sizeof( T ) ) ) T
# define MYDEL( ptr ) if (ptr) { g_Allocator->Destructor(ptr); g_Allocator->Dealloc(ptr); }

Then, i can use MYNEW to construct object( also trace alloc info for check memory leak ), and MYDEL to destroy object( erase trace info ).

Everything looks fine... but, when i try to use this method for multiple inheritance class, i found a very serious problem. look my test code below:

class A { ... };
class B { ... };
class C : public A, public B { ... };

C* pkC = MYNEW( C );
B* pkB = (B*)pkA;
MYDEL( pkB );

the address of pkB and pkA does not equal. so the memory will not free correct, and the alloc trace info will not erase coorect too...oh...

Is there any way to solve this problem?


回答1:


If ptr points to an instance of a polymorphic class, dynamic_cast<void*>(ptr) will result in a pointer to the most derived object pointed to by ptr. In other words, this dynamic cast yields a pointer to the as-allocated address.

However, using g_Allocator->Dealloc(dynamic_cast<void*>(ptr)) is not a viable solution. The problem is that dynamic_cast<void*>(ptr) is illegal if ptr points to a non-class object (e.g., a primitive) or to an instance of a non-polymorphic class.

What you can do is use SFINAE to create a function that uses this dynamic cast for pointers to polymorphic classes but uses a static cast for pointers to non-class objects and instances of non-polymorphic classes. Boost (and now C++11) provides is_class<T> and is_polymorphic<T> type traits that will help in this regard.

Example:

template <typename T, bool is_poly>
struct GetAllocatedPointerHelper {
   static void* cast (T* ptr) { return ptr; }
};

template <typename T>
struct GetAllocatedPointerHelper<T, true> {
   static void* cast (T* ptr) { return dynamic_cast<void*>(ptr); }
};

template<typename T>
inline void*
get_allocated_pointer (T* ptr)
{
   const bool is_poly = Boost::is_polymorphic<T>::value;
   return GetAllocatedPointerHelper<T, is_poly>::cast(ptr);
}



回答2:


You can try to override operators new and delete for a base class and derive all your classes where you want your custom allocators from that class. Following a simple sample:

#include <cstdio>
#include <cstdlib>

class Base
{
    public:
        virtual ~Base(){};

        void* operator new(size_t size){return malloc(size);}
        void operator delete(void* pointer){printf("\n%x\n", pointer); free(pointer);}
};

class A : public virtual Base
{
    public:
        ~A(){printf("~A");};
};

class B : public virtual Base
{
    public:
        ~B(){printf("~B");};
};

class C : public A, public B
{
    public:
        ~C(){printf("~C");};
};

int main()
{
    C* c = new C();
    printf("%x\n", c);

    B* b = dynamic_cast<B*>(c);
    printf("%x\n", b);

    delete b;

    return 0;
}

One possible output is:

5831d0 5831d4 ~C~B~A 5831d0

In this case operator delete received correct address.



来源:https://stackoverflow.com/questions/13705427/custom-memory-alloc-and-dealloc-which-multiple-inheritance-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!