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?
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:
One possible output is:
In this case operator delete received correct address.
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 byptr
. 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 thatdynamic_cast<void*>(ptr)
is illegal ifptr
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>
andis_polymorphic<T>
type traits that will help in this regard.Example: