Можно ли переключить среду выполнения Visual C ++ на другую кучу? - PullRequest
6 голосов
/ 15 марта 2010

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

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

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

Ответы [ 2 ]

3 голосов
/ 15 марта 2010

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

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

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

Смутно как-то так:

//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);
}

в приложении load

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, если только для этого не было особой причины.

0 голосов
/ 15 марта 2010

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...