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
477 views
in Technique[技术] by (71.8m points)

c++ - Custom memory alloc and dealloc which multiple Inheritance class

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?

See Question&Answers more detail:os

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

1 Answer

0 votes
by (71.8m points)

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);
}

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

...