Кто-нибудь смог интегрировать tcmalloc в 64-битное приложение Windows, которое использует общие библиотеки DLL?

У меня есть 64-битное приложение Visual Studio 2010 (однопоточное) C ++ для Windows, с которым я пытаюсь интегрировать tcmalloc, и у меня возникают проблемы при использовании любой из наших динамически связанных библиотек DLL. Я связал tcmalloc как статическую библиотеку. tcmalloc прекрасно работает, пока приложение не начнет использовать одну из наших общих библиотек DLL. Я построил решение как 64-битное приложение DEBUG. Все ссылки на dll с отладочными версиями библиотек CRT на C / C ++ (MSVCP100D.dll и MVCR100D.dll).

Ниже приведен пример кода, который не работает. tcmalloc вызывается для всех выделений памяти, но когда вызывается delete, происходит сбой приложения. Это действительно озадачивает меня, так как точно такой же код работает нормально, когда я создал функцию в главном исполняемом файле и скопировал туда код.

Если у кого-то есть опыт использования tcmalloc в такой ситуации, я буду признателен за ваш отзыв. Это для меня загадка. Это проблема модели памяти с DLL (разные кучи ??)? Я не знаю. Мне кажется, они используют одну и ту же кучу.

Извините, если этот пост слишком длинный. Я пытался дать как можно больше информации.

Спасибо.

Брюс

Обновление: в качестве теста я изменил разделяемую dll, где она вылетала, на статическую библиотеку и все работало нормально, пока приложение не использовало другую dll. Так что по любой причине tcmalloc требует некоторых дополнительных шагов для обработки общих DLL. Я могу сделать все статические библиотеки нашего dll для профилирования памяти с помощью tcmalloc, но было бы очень приятно узнать, что еще нужно сделать, чтобы использовать shared
DLL с Tcmalloc.

Объявление метода файла заголовка DLL:
__declspec (dllexport) static std :: string GetExecutablePath ();

//.cpp реализация

string Parameters::GetExecutablePath()

string  execPathStr;
char exeFilePath[ MAX_PATH +1];
if ( GetModuleFileName( NULL, exeFilePath, MAX_PATH ) )
{
//The line of code below is where the app crashes.
//It calls operator new in crt/src/new.cpp. I verified the call to malloc
//is forwarded to tcmalloc.
*execPathStr = string(exeFilePath);* //creates and deletes a temporary and then crashes

long dir_pos = execPathStr.rfind( FT_DIR_SLASH ) ;
execPathStr = execPathStr.substr( 0, dir_pos+1 );
}

return execPathStr;

}

Методы, вызываемые, когда временная строка уничтожается:

~_String_val()
{
// destroy the object
typename _Alloc::template rebind<_Container_proxy>::other _Alproxy(_Alval);
this->_Orphan_all();
_Dest_val(_Alproxy, this->_Myproxy);
**_Alproxy.deallocate(this->_Myproxy, 1);**
this->_Myproxy = 0;
}void deallocate(pointer _Ptr, size_type)
{
// deallocate object at _Ptr, ignore size
**::operator delete(_Ptr);**
}

This is where it crashes. the pHead->nBlockUse is 0.
crt/dbgdel.cpp:

void operator delete(
void *pUserData
)
{
//code omitted for brevity
/* verify block type */
**_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));** //crashes here
}

После перестройки tcmalloc как общей библиотеки DLL теперь происходит сбой в другом месте при попытке освободить память.

afxmem.cpp:

void __cdecl operator delete(void* p)
{
#if !defined(_AFX_NO_DEBUG_CRT) && defined(_DEBUG)
**_free_dbg(p, _NORMAL_BLOCK);** <-------- this function gets called
#else
free(p);
#endif
}

dbgheap.c:

extern "C" _CRTIMP void __cdecl _free_dbg(
void * pUserData,
int nBlockUse
)
{
_mlock(_HEAP_LOCK);

__try {
/* allocate the block
*/
**_free_dbg_nolock(pUserData, nBlockUse);**
}
__finally {
/* unlock the heap
*/
_munlock(_HEAP_LOCK);
}
}extern "C" void __cdecl _free_dbg_nolock(
void * pUserData,
int nBlockUse
)
{
//code omitted for brevity

/*
* If this ASSERT fails, a bad pointer has been passed in. It may be
* totally bogus, or it may have been allocated from another heap.
* The pointer MUST come from the 'local' heap.
*/
**_ASSERTE(_CrtIsValidHeapPointer(pUserData));** <-------- crashes here
}

4

Решение

Путем статического связывания tcmalloc каждая используемая DLL-библиотека получает собственную копию внутреннего состояния библиотеки (включая кучу и все указатели). Если вы выделите память через tcmalloc из одной DLL и попытаетесь удалить из другой, операция завершится неудачно, потому что вы в конечном итоге получите доступ к нескольким кучам.

Свяжите tcmalloc как динамическую библиотеку, и ваша проблема должна исчезнуть.

1

Другие решения

Наконец-то у нас работает tcmalloc на 64-битной платформе Windows с общими библиотеками DLL. Спасибо капитану Oblivious за его предложения! Хитрость заключалась в том, чтобы создать выпускную версию в Visual Studio 2010 с символами отладки, как указано в этой статье: Как отладить сборку релиза . У tcmalloc есть конфликты с вызовами кучи отладки CRT в MFC, такими как: _free_dbg. Мы выделяли память из tcmalloc и освобождали от вызовов отладки кучи MFC CRT. В сборке релиза эта проблема исчезла. Мы провели предварительное тестирование, и tcmalloc генерирует граф вызовов профиля кучи.

Благодарю.

Брюс

1

По вопросам рекламы [email protected]