Моя программа использует стороннюю динамически подключаемую библиотеку, которая имеет огромные утечки памяти внутри. И моя программа и библиотека являются собственным кодом Visual C++. Обе ссылки на время выполнения Visual C++ динамично.
Я хотел бы вынудить библиотеку в другую "кучу" так, чтобы все выделения, которые сделаны через время выполнения Visual C++, в то время как код библиотеки работает, были сделаны на той "куче". Я могу звонить HeapCreate()
и позже HeapDestroy()
. Если я так или иначе удостоверяюсь, что все выделения сделаны в новой "куче", о которой я больше не забочусь утечек - они все идут, когда я уничтожаю вторую "кучу".
Действительно ли возможно вынудить время выполнения Visual C++ сделать все выделения на указанной "куче"?
Извините, мой последний ответ был наполовину напечатан, я нажал табуляцию и ввел, не помня, что это текстовое поле, а не редактор ...
В любом случае, вот это полностью:
Вы можете использовать библиотеку обходных путей, чтобы перехватить функции выделения и освобождения, заменив их своими собственными:
Примерно что-то вроде этого:
//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, если только не было особой причины не делать этого.
Перенаправление только выделений DLL в лучшем случае будет сложным, если оба двоичных файла ссылаются на нее одинаково.
Самый надежный способ, который я могу придумать, это перемещение DLL в отдельный процесс. Это довольно просто для COM DLL, которая использует только интерфейсы IDispatch или предоставляет прокси/концентратор DLL. В противном случае вам придется написать собственную обертку - в зависимости от API DLL это потребует много работы или может стать проблемой производительности.
Если требуется оставаться в процессе, можно подключить выделения CRT и перенаправить выделения, сделанные библиотекой, в другой распределитель (например, в кучу Win32).
Наиболее безопасным решением будет обертывание всех вызовов библиотеки, устанавливающих глобальный флаг. В качестве альтернативы можно просмотреть стек вызовов - но это сработает не во всех сценариях. При обоих решениях следите за обратными вызовами, реализованными в вашем коде, но вызываемыми библиотекой.
[edit] _CRTSetAllocHook работает только в отладочных буях.