Une fuite de mémoire lors du déchargement d'une DLL provoque-t-elle une fuite dans le processus hôte?

StackOverflow https://stackoverflow.com/questions/132242

Question

Considérez ce cas:

dll = LoadDLL()
dll->do()

...
void do() {
    char *a = malloc(1024);
}
...

UnloadDLL(dll);

À ce stade, le 1k alloué dans l'appel à malloc () sera à nouveau disponible pour le processus hôte? La DLL est liée statiquement au CRT.

Était-ce utile?

La solution

Non, vous ne fuyez pas.

Si vous mélangez des modèles de dll (statiques, dynamiques), vous pouvez vous retrouver avec une erreur de mémoire si vous allouez de la mémoire dans une dll, que vous libérez dans un autre (ou libéré dans l'exe)

Cela signifie que le segment créé par le tube cathodique lié statiquement n'est pas le même segment que le tube cathodique d'une dll différente.

Si vous aviez établi un lien avec la version dynamique du tube cathodique, vous auriez une fuite car le segment de mémoire est partagé entre tous les tubes cathodiques liés dynamiquement. Cela signifie que vous devez toujours concevoir vos applications de manière à utiliser les tubes cathodiques dynamiques, ou vous assurer de ne jamais gérer la mémoire sur une limite de DLL (par exemple, si vous allouez de la mémoire dans une DLL, fournissez toujours une routine pour la libérer dans la même DLL).

Autres conseils

  1. La mémoire utilisée par un processus tel que suivi par le système d'exploitation s'applique à l'ensemble du processus et n'est pas spécifique à une DLL.

  2. La mémoire est donnée au programme en morceaux par le système d'exploitation, appelée tas

  3. Les gestionnaires de segments de mémoire (malloc / new, etc.) divisent davantage les morceaux et les transmettent au code demandeur.

  4. Ce n'est que lorsqu'un nouveau segment de mémoire est alloué que le système d'exploitation détecte une augmentation de la mémoire.

  5. Lorsqu'une DLL est liée de manière statique à la bibliothèque CRT (Run Time Library) C, une copie privée de CRT avec les fonctions CRT invoquées par le code de la DLL est compilée et placée dans le fichier binaire de la DLL. Malloc est également inclus dans ce domaine.

  6. Cette copie privée de malloc sera invoquée chaque fois que le code présent dans la DLL liée de manière statique tente d'allouer de la mémoire.

  7. Par conséquent, un mall privé visible uniquement par cette copie de malloc est acquis à partir du système d'exploitation par ce malloc et alloue la mémoire demandée par le code contenu dans ce segment privé.

  8. Lorsque la DLL est déchargée, elle décharge son segment de mémoire privé. Cette fuite passe inaperçue lorsque le segment de mémoire entier est renvoyé au système d'exploitation .

  9. Cependant, si la DLL est liée dynamiquement, la mémoire est allouée par une seule version partagée de malloc, globale pour tout le code lié en mode partagé.

  10. La mémoire allouée par ce malloc global, provient d'un tas qui est également le tas utilisé pour tout autre code lié au mode dynamique dit partagé et qui est donc commun. Toute fuite de ce tas devient donc une fuite qui affecte tout le processus.

Modifier - Ajout de descriptions du scénario de liaison.

Vous ne pouvez pas dire. Cela dépend de la mise en œuvre de votre tube cathodique statique et dynamique. Cela peut même dépendre de la taille de l'allocation, car certains CRT transmettent d'importantes allocations au système d'exploitation, mais implémentent leur propre tas pour les petites allocations.

Le problème avec un tube cathodique qui fuit est bien sûr qu'il fuit. Le problème avec un tube cathodique qui ne fuit pas est que l'exécutable peut raisonnablement s'attendre à utiliser la mémoire, car la mémoire de malloc doit rester utilisable jusqu'à ce que l'appel de free soit appelé.

De MSDN Erreurs potentielles lors de la transmission d'objets CRT à travers les limites de DLL

  

Chaque copie de la bibliothèque CRT a un   Etat séparé et distinct. En tant que tel,   Objets CRT tels que les descripteurs de fichiers,   les variables d'environnement, et les lieux sont   valable uniquement pour la copie du tube cathodique   où ces objets sont alloués ou   ensemble. Quand une DLL et ses utilisateurs utilisent   différentes copies de la bibliothèque CRT,   vous ne pouvez pas transmettre ces objets CRT   à travers la limite de la DLL et attendre   qu'ils soient pris correctement sur le   de l'autre côté.

     

En outre, chaque copie du tube cathodique   la bibliothèque a son propre gestionnaire de tas,   Allocation de mémoire dans une bibliothèque CRT   et en passant le pointeur sur une DLL   frontière à libérer par un autre   copie de la bibliothèque CRT est un potentiel   cause de corruption de tas.

J'espère que cela vous aidera.

En fait, la réponse marquée est incorrecte. Ce droit il y a une fuite. Bien qu’il soit techniquement possible pour chaque dll d’implémenter son propre segment de mémoire et de le libérer à l’arrêt, la plupart des "runtime" Les tas - statiques ou dynamiques - enveloppent l'API du tas de processus Win32.

À moins que vous n'ayez pris un soin particulier à vous garantir que ce ne soit pas le cas, la dll divulguera l'allocation par charge, effectuez le cycle de déchargement.

On peut faire un test et voir s’il ya des fuites de mémoire. Vous exécutez un simple test 30 fois, en allouant 1 Mo à chaque fois. Vous devriez comprendre cela assez rapidement.

Une chose est sûre. Si vous avez alloué de la mémoire dans la DLL, vous devez également la libérer (dans la DLL).

Par exemple, vous devriez avoir quelque chose comme ceci (pseudocode simple mais intuitif):

dll = DllLoad();

ptr = dll->alloc();

dll->free(ptr);

DllUnload(dll);

Cela doit être fait car la DLL a un segment de mémoire différent du processus d'origine (qui charge la dll).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top