Я могу переключить время выполнения Visual C++ на другую "кучу"?

Моя программа использует стороннюю динамически подключаемую библиотеку, которая имеет огромные утечки памяти внутри. И моя программа и библиотека являются собственным кодом Visual C++. Обе ссылки на время выполнения Visual C++ динамично.

Я хотел бы вынудить библиотеку в другую "кучу" так, чтобы все выделения, которые сделаны через время выполнения Visual C++, в то время как код библиотеки работает, были сделаны на той "куче". Я могу звонить HeapCreate() и позже HeapDestroy(). Если я так или иначе удостоверяюсь, что все выделения сделаны в новой "куче", о которой я больше не забочусь утечек - они все идут, когда я уничтожаю вторую "кучу".

Действительно ли возможно вынудить время выполнения Visual C++ сделать все выделения на указанной "куче"?

6
задан sharptooth 15 March 2010 в 11:22
поделиться

2 ответа

Извините, мой последний ответ был наполовину напечатан, я нажал табуляцию и ввел, не помня, что это текстовое поле, а не редактор ...

В любом случае, вот это полностью:

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

Примерно что-то вроде этого:

//declare a global 
HANDLE g_currentHeap;

LPVOID WINAPI HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes) 
{ 
    return OriginalHeapAlloc(g_currentHeap, dwFlags, dwBytes);
}


BOOL WINAPI HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem)
{
    return OriginalHeapFree(g_currentHeap, dwFlags, lpMem);
}

в загрузке приложения

HANDLE g_Heaps[2];

int main()
{
    // Two heaps
    g_Heaps[0] = HeapCreate(...);
    g_Heaps[1] = HeapCreate(...);


    // Do whatevers needed to hook HeapAlloc and HeapFree and any other heap functions 
    // and redirect them to the versions above
    // Save the old function pointers so we can call them
}

Затем каждый раз, когда вы вызовите API из сторонней DLL, вы можете сделать это

void someFn()
{
    g_currentHeap = g_Heaps[1];
    Some3rdPartyAPI();
    g_currentHeap = g_Heaps[0];

    SomeOtherFunction();

}

Это должно решить вашу проблему

@peterchen: Среда выполнения C ++ вызывает HeapAlloc для new и malloc (), поэтому этот подход будет работать. Фактически, я считаю, что почти любая среда выполнения языков будет использовать функции кучи win32, если только не было особой причины не делать этого.

3
ответ дан 17 December 2019 в 18:13
поделиться

Перенаправление только выделений DLL в лучшем случае будет сложным, если оба двоичных файла ссылаются на нее одинаково.

Самый надежный способ, который я могу придумать, это перемещение DLL в отдельный процесс. Это довольно просто для COM DLL, которая использует только интерфейсы IDispatch или предоставляет прокси/концентратор DLL. В противном случае вам придется написать собственную обертку - в зависимости от API DLL это потребует много работы или может стать проблемой производительности.

Если требуется оставаться в процессе, можно подключить выделения CRT и перенаправить выделения, сделанные библиотекой, в другой распределитель (например, в кучу Win32).

Наиболее безопасным решением будет обертывание всех вызовов библиотеки, устанавливающих глобальный флаг. В качестве альтернативы можно просмотреть стек вызовов - но это сработает не во всех сценариях. При обоих решениях следите за обратными вызовами, реализованными в вашем коде, но вызываемыми библиотекой.

[edit] _CRTSetAllocHook работает только в отладочных буях.

0
ответ дан 17 December 2019 в 18:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: