自定义内存alloc和dealloc多个继承类

xfx*_*rld 11 c++ memory-management game-engine

我想在我的项目中进行内存管理.我不希望operator global new/delete所以我实现了一个简单的内存alloctor.这是我的代码:

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); }
Run Code Online (Sandbox Code Playgroud)

然后,我可以使用MYNEW来构造对象(还有用于检查内存泄漏的跟踪alloc信息),以及用于销毁对象的MYDEL(擦除跟踪信息).

一切看起来很好......但是,当我尝试将此方法用于多继承类时,我发现了一个非常严重的问题.看下面我的测试代码:

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

C* pkC = MYNEW( C );
B* pkB = (B*)pkA;
MYDEL( pkB );
Run Code Online (Sandbox Code Playgroud)

pkB和pkA的地址不相等.所以内存不会自由纠正,而且分配跟踪信息也不会擦除coorect ...哦......

有什么方法可以解决这个问题吗?

Dav*_*men 7

如果ptr指向多态类的实例,dynamic_cast<void*>(ptr)将导致指向指向的最派生对象的指针ptr.换句话说,此动态转换产生指向分配地址的指针.

但是,使用g_Allocator->Dealloc(dynamic_cast<void*>(ptr))不是一个可行的解决方案.问题是dynamic_cast<void*>(ptr)如果ptr指向非类对象(例如,基元)或非多态类的实例则是非法的.

你可以做的是使用SFINAE来创建一个函数,该函数使用这个动态转换来指向多态类,但是使用静态转换来指向非类对象和非多态类的实例.提升(现在C++ 11)提供is_class<T>is_polymorphic<T>类型特征,将在这方面提供帮助.

例:

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);
}
Run Code Online (Sandbox Code Playgroud)

  • +1,今天拿起一个新东西(`dynamic_cast`,没意识到它那样做了......) (2认同)