2009-08-18 4 views
1

Я внедрил пользовательский распределитель (который будет использоваться контейнерами STL в моей утилите для отладки памяти без использования моего переопределенного нового оператора). Внутри отладчика памяти я использую экземпляр того же класса распределителя для выделения объектов, которые мне нужны, чтобы отслеживать «нормальные» распределения памяти. Все работает нормально, но я не уверен, правильно ли я использую интерфейс распределителя. Вот методы полезности, поскольку они в настоящее время стоят (правильные параметры инициализации для входа будет добавлено в ближайшее время):Каков правильный способ создания объекта с помощью распределителя?

iidebug::CMemoryDebugger::CEntry* iidebug::CMemoryDebugger::NewEntry() 
{ 
    CEntry* pEntry = m_entryAllocator.allocate(1); 
    if (0 != pEntry) 
    { 
     new(pEntry) CEntry(0, 0, __FILE__, 0, 0, 0); 
    } 
    return pEntry; 
} 

void iidebug::CMemoryDebugger::DeleteEntry(iidebug::CMemoryDebugger::CEntry* pEntry) 
{ 
    if (0 != pEntry) 
    { 
     destruct(pEntry); 
     m_entryAllocator.deallocate(pEntry, 1); 
    } 
} 

Это только кажется, очень грязный, но я не могу понять, как я могу улучшить его.

ответ

1

Вы можете реально перегружать новые и удалять, чтобы принять параметр распределителя, например, так:

inline void *operator new(size_t sizeT, Allocator *&a) { 
    return a->allocate(sizeT); 
} 

inline void operator delete(void * mem, Allocator *&a) { 
    a->release(mem); 
} 

int main() 
{ 
    Allocator * a = new Allocator; 
    C *c = new(a) C; 
    c->~C(); 
    operator delete(c, a); 
    return 0; 
} 

Смотрите wikipedia article более подробно. Это все еще немного грязно, потому что вы должны быть уверены, что не будете вызывать обычный оператор удаления, если ваш распределитель делает что-то особенное.

+0

Это намного опрятный вариант, спасибо стек :) – FlintZA

+1

Что-то, что мне нравится делать, также переопределяет новый оператор по умолчанию, так что все распределения иметь указатель функции в начале выделения (нужно добавить дополнительные 4 байта при работе в 32-битном приложении x86), что указывает на функцию dealloc съел память. затем, когда вы удаляете объект (все объекты могут быть удалены с помощью операторов удаления по умолчанию с этим), вы просто вызываете этот указатель функции. –

+0

Интересная идея, это для отладки памяти? Если он находится в новом по умолчанию, и тот же самый указатель функции всегда передается, почему бы просто не вызвать функцию явно внутри переопределенного удаления вместо того, чтобы принимать дополнительные 4 байта на каждый указатель? – FlintZA

0

Что такое destruct? Я предполагаю, что это должно быть:

void iidebug::CMemoryDebugger::DeleteEntry(iidebug::CMemoryDebugger::CEntry* pEntry) 
{ 
    if (0 != pEntry) 
    { 
     pEntry->~CEntry(); 
     m_entryAllocator.deallocate(pEntry, 1); 
    } 
} 
+0

К сожалению о том, что разрушится один из трех вспомогательных функций, реализованных для обработки разрушения, как в HTTP: //www.codeguru.com/cpp/cpp/cpp_mfc/stl/article.php/c4079 – FlintZA

1

Для справки в случае, если кто-либо пытается использовать код Дрю, ему необходимо несколько настроек. Ниже то, что я в конечном итоге с помощью:

template <typename T> 
void* operator new(SizeT iSize, SimpleAllocator<T>& rAllocator) 
{ 
    return rAllocator.allocate(1); 
} 

template <typename T> 
void operator delete(void* pvMemory, SimpleAllocator<T>& rAllocator) 
{ 
    ((T*)pvMemory)->~T(); 
    rAllocator.deallocate(pvMemory, 1); 
} 

И на самом деле, используя это так же просто, как:

// SimpleAllocator<CFoo> fooAllocator = ... 
CFoo* pFoo = new(fooAllocator) CFoo(param1, param2, ...); 
// Do stuff with pFoo... 
operator delete(pFoo, fooAllocator); 
Смежные вопросы