2010-03-15 2 views
6

Mon programme utilise une bibliothèque de liens dynamiques tierce qui présente d'énormes fuites de mémoire à l'intérieur. Mon programme et la bibliothèque sont le code natif Visual C++. Les deux lier dynamiquement à l'exécution Visual C++. Je voudrais forcer la bibliothèque dans un autre tas de sorte que toutes les allocations qui sont effectuées via l'exécution Visual C++ pendant que le code de bibliothèque est en cours d'exécution sont effectuées sur ce segment. Je peux appeler HeapCreate() et plus tard HeapDestroy(). Si je m'assure d'une façon ou d'une autre que toutes les allocations sont faites dans le nouveau tas, je m'en fiche des fuites - elles vont toutes quand je détruis le second tas.Puis-je passer le runtime Visual C++ à un autre tas?

Est-il possible de forcer l'exécution Visual C++ pour effectuer toutes les allocations sur un tas spécifié?

+0

Comment liez-vous à la bibliothèque? – GManNickG

+0

@GMan: Le programme lie dinamiquement à la bibliothèque. – sharptooth

+0

Comment la DLL se lie-t-elle à l'exécution? –

Répondre

3

Désolé ma dernière réponse obtenu a posté bancales, je pressai onglet et entrer sans se rappeler c'était une zone de texte et non un éditeur ...

Quoi qu'il en soit Heres en entier:

Vous pouvez utiliser la bibliothèque pour accrocher des détours les fonctions d'allocation et désallocation, les remplacer par votre propre:

Vaguement quelque chose comme ceci:

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

la charge de l'application

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 
} 

Ensuite, chaque fois que vous appelez une API de la DLL 3ème partie, vous pouvez le faire

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

    SomeOtherFunction(); 

} 

Cela devrait résoudre votre problème

@peterchen: Le temps d'exécution C++ appelle HeapAlloc pour new et malloc(), cette approche fonctionnera. En fait, je crois que presque toutes les langues runtime utiliseront les fonctions win32 Heap, à moins qu'il y ait une raison spéciale de ne pas le faire.

+0

Au moins dans VC6, HeapAlloc a toujours été appelé dans Debug Builds, dans Release Builds, un gestionnaire de mémoire personnalisé a été lancé pour les allocations msot. * Je ne sais pas * si cela a changé dans VS2005/2008 - doit être vérifié. – peterchen

+0

La source CRT pour Visual Studio 8 ne semble appeler HeapAlloc() Je mis un point d'arrêt sur HeapAlloc() en mode de libération sur un programme de test .... Paraît qu'il est appelé à chaque malloc() et nouveau. –

+0

Detours est très utile, mais il faut faire attention surtout s'il y a plusieurs threads. J'ai rencontré des problèmes très complexes avec le débogage. Le meilleur pari, si vous choisissez de l'utiliser, est d'initialiser et de configurer toutes vos fonctions détourées avant de charger d'autres DLL ou de démarrer des threads autres que le principal. Sinon, vous pouvez vous retrouver dans des situations difficiles où un autre thread peut déjà être dans la fonction que vous essayez de détourner. – cpalmer

0

Redirection seulement les allocations de la DLL est au mieux difficile si les deux binaires lier à la même manière.

La manière la plus robuste que je peux penser est de déplacer la DLL dans un processus séparé. C'est assez facile pour une DLL COM qui utilise uniquement des interfaces IDispatch ou fournit une DLL proxy/stub. Sinon, vous devrez écrire un wrapper personnalisé - selon l'API de la DLL, cela représente beaucoup de travail ou peut être un problème de performance.

Si vous devez rester en cours de traitement, vous pouvez raccorder des allocations CRT et rediriger les allocations effectuées par la bibliothèque vers un autre allocateur (tel qu'un tas Win32). La décision de mine/leur serait plus sûre en enveloppant tous les appels à la bibliothèque qui définit un drapeau global. Alternativement, vous pouvez inspecter la pile de tous les appels - mais cela ne fonctionnera pas dans tous les scénarios. Avec les deux solutions, faites attention au rappel implémenté dans votre code mais appelé par la bibliothèque.

[edit] _CRTSetAllocHook ne fonctionne que dans les buils de débogage.

+0

Les allocations d'accrochage fonctionneront-elles pour la version non-debug du CRT? – sharptooth

+0

Vous avez raison, _CrtSetDebugHook ne fonctionne que dans les versions de débogage. Vous pouvez vérifier les détours comme suggéré par rep_movsd s'ils travaillent dans des versions de versions pour toutes les allocations. Sinon ... un google rapide ne révèle rien de concluant. Peut-être attendez-vous d'autres réponses, ou ouvrez-le comme une nouvelle question. – peterchen

Questions connexes