2010-03-15 71 views
6

我的程序使用第三方動態鏈接庫,其內部存在大量內存泄漏。我的程序和庫都是Visual C++本機代碼。兩者都動態鏈接到Visual C++運行時。我可以將Visual C++運行時切換到另一堆嗎?

我想迫使庫進入另一堆,以便所有通過Visual C++運行庫在庫代碼運行時完成的分配都在堆上完成。我可以撥打HeapCreate()及更高版本HeapDestroy()。如果我以某種方式確保所有分配都在新堆中完成,我不再在意泄漏 - 當我摧毀第二堆時,它們全部消失。

是否有可能強制Visual C++運行庫在指定的堆上進行所有分配?

+0

你如何鏈接到圖書館? – GManNickG 2010-03-15 07:23:09

+0

@GMan:程序以圖形方式鏈接到圖書館。 – sharptooth 2010-03-15 07:33:42

+0

DLL如何鏈接到運行時? – 2010-03-15 11:35:51

回答

3

對不起我最後得到的答案貼半生不熟,我按下選項卡,無需記住這是一個文本框,而不是一個編輯器中輸入...

反正繼承人它在全:

您可以使用少走彎路庫掛鉤的分配和釋放功能,用自己替換它們:

依稀是這樣的:

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

然後每次你打電話從第三方DLL的API,你可以做到這一點

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

    SomeOtherFunction(); 

} 

這應該解決您的問題

@peterchen:C++運行時調用HeapAlloc對於新的和malloc(),所以這種方法將工作。事實上,我相信幾乎所有的語言運行時都會使用win32 Heap函數,除非有一個特殊的原因。

+0

至少在VC6中,HeapAlloc總是在Debug Builds中的Release Builds中調用,這是一個自定義內存管理器,用於msot分配。 *我不知道*如果VS2005/2008發生了變化 - 需要驗證。 – peterchen 2010-03-15 12:04:50

+0

爲Visual Studio 8的CRT源似乎並調用HeapAlloc() 我在釋放模式將斷點上HeapAlloc()上的測試程序.... 似乎是被稱爲每個的malloc()和新的。 – 2010-03-15 14:07:34

+0

Detours非常有用,但如果有多個線程,尤其需要小心。我遇到了一些非常棘手的問題,用它進行調試。最好的選擇是,如果你選擇使用它,那麼在加載任何其他DLL或啓動除主函數以外的任何線程之前,首先要初始化並設置所有繞行函數。否則,您可能會遇到棘手的情況,其中另一個線程可能已經在您嘗試繞行的功能中。 – cpalmer 2010-04-02 00:40:28

0

重定向只有如果兩個二進制文件以相同的方式鏈接到它,DLL的分配最多是棘手的。

我能想到的最穩健的方法是將DLL移動到單獨的進程中。對於僅使用IDispatch接口或提供代理/存根DLL的COM DLL,這是相當容易的。否則,你需要編寫一個自定義的包裝器,這取決於DLL的API,它有很多工作或者可能是一個性能問題。

如果需要保持進行中,您可以掛鉤CRT分配,並將庫所做的分配重定向到另一個分配器(例如Win32堆)。

礦山/他們的決定最安全的做法是將所有調用包裝到設置全局標誌的庫中。或者,您可以檢查呼叫堆棧 - 但這不適用於所有情況。使用這兩種解決方案,請注意代碼中實現的回調,但由庫調用。

儘管如此,_CRTSetAllocHook只能在調試版中使用。

+0

鉤子分配是否適用於CRT的非調試版本? – sharptooth 2010-03-15 12:02:05

+0

你說得對,_CrtSetDebugHook也只適用於調試版本。如果他們在所有分配的發佈版本中工作,則可以按照rep_movsd的建議檢查出路程。否則...一個快速的谷歌沒有任何結論。也許等待其他答覆,或將其作爲一個新問題打開。 – peterchen 2010-03-15 13:49:35

相關問題