La libération de la mémoire allouée dans une autre DLL
J'ai un fichier EXE en utilisant un fichier DLL qui est d'utiliser un autre fichier DLL. Cette situation a été soulevée:
En fichier DLL 1:
class abc
{
static bool FindSubFolders(const std::string & sFolderToCheck,
std::vector< std::string > & vecSubFoldersFound);
}
En fichier DLL 2:
void aFunction()
{
std::vector<std::string> folders;
std::string sLocation;
...
abc::FindSubFolders(sLocation, folders)
}
En mode release, tout fonctionne bien. Mais en mode debug, je viens avec un échec d'assertion dans le destructeur de l'un des std::strings
dans les dossiers vecteur (lorsque les dossiers sont est hors de portée à la fin de aFunction):
dbgheap.c : line 1274
/*
* If this ASSERT fails, a bad pointer has been passed in. It may be
* totally bogus, or it may have been allocated from another heap.
* The pointer MUST come from the 'local' heap.
*/
_ASSERTE(_CrtIsValidHeapPointer(pUserData));
Je suppose que c'est parce que la mémoire a été allouée sur le fichier DLL 1 du tas, mais est libéré dans le fichier DLL 2.
Le commentaire dans dbgheap.c
semble assez insisté sur le fait que c'est un problème.
Pourquoi est-ce un tel problème, quand il semble que cela fonctionne bien si je l'ignore tout simplement? Est-il un non-affirmation-à défaut de moyen de le faire?
PAS. En l'IGNORANT. C'. C'EST. POURQUOI. I. DEMANDÉ. =P
Je veux juste savoir pourquoi c'est un problème.
OriginalL'auteur Smashery | 2009-10-28
Vous devez vous connecter pour publier un commentaire.
Que sean l'a déjà dit, la version release ignore simplement que l'instruction delete, donc le mieux que vous pouvez espérer, c'est une fuite de mémoire.
Si vous avez le contrôle sur la façon dont les deux DLL, les fichiers sont compilés, assurez-vous d'utiliser le Multi-thread DLL de Débogage (/Tdm) ou DLL multithread (/MD) paramètres de la bibliothèque d'exécution. De cette façon, les deux fichiers DLL utilisent le même système d'exécution et de partager le même tas.
L'inconvénient est que vous devez installer le système d'exécution en collaboration avec votre application (Microsoft propose un programme d'installation pour que). Il fonctionnera parfaitement sur votre machine de développement depuis Visual Studio installe que le système d'exécution de trop, mais sur un fraîchement installé machine, il fera rapport de DLL fichiers manquants.
OriginalL'auteur Hans
Que d'autres dit, le problème peut être résolu en faisant en sorte que le CRT est partagé entre les deux modules. Mais il y a des scénarios courants où le présent contrat est difficile à appliquer.
La raison en est que faire en sorte de lien à l'encontre d'un partagées CRT ne fonctionnera pas si l'EXE et les DLL n'a pas de lien à l'encontre de la même CRT version (comme dans la version 6.0, 7.0, 8.0). Par exemple, si vous prenez une DLL qui a été construit en VC6.0 et essayez de l'utiliser avec un EXE construire dans VS2010, vous obtiendrez le même problème qu'avant. Les deux versions de la CRT seront chargés dans votre processus et chaque utilisation de leur propre tas d'allocation, peu importe si votre EXE et DLL "partagée" CRT, ils ne seront pas les mêmes.
Une meilleure pratique pour une API serait de faire en sorte que les objets alloués dans l'un des côtés sont également détruits sur le même côté. Je sais que cela paraît laid, mais c'est la seule manière de garantir qu'une DLL reste compatible binaire.
OriginalL'auteur erbi
Le plus probable, la version release a le même problème, mais les versions release de ne pas faire valoir. Ils ont juste ignorer le problème. Vous pourriez ne jamais voir un problème. Ou vous pourriez voir à la corruption de données. Ou vous pourriez voir un crash. Peut-être que vos utilisateurs une expérience de bugs que vous ne sont tout simplement pas en mesure de se reproduire.
Ne pas ignorer les CRT affirmations.
Vous devriez toujours utiliser le deallocator (celui qui correspond à l'allocateur utilisé pour commencer). Si vous utilisez statiques des bibliothèques CRT dans votre DLL fichiers, les fichiers DLL sont à l'aide de différents tas. Vous ne pouvez pas désallouer de la mémoire à travers les tas. Allouer et de libérer un bloc de la mémoire en utilisant le même tas.
Si l'utilisation partagée des bibliothèques CRT dans vos fichiers de DLL, il devrait être en utilisant le même tas et vous pouvez allouer dans un fichier DLL et de libérer dans l'autre.
+1, je vous Remercie!
OriginalL'auteur sean e
C'est seulement un problème si l'application ou de l'une (ou plusieurs) des fichiers DLL est lié à l'encontre de la version statique de la bibliothèque standard. Cela a été résolu il y a dix ans par MME libérant une version de bibliothèque partagée de la bibliothèque standard. C'est parce que chaque version de la bibliothèque standard va construire interne tas et donc avec plusieurs tas, vous devez libérer de la mémoire pour le bon segment. En utilisant la version partagée de la bibliothèque standard, ils utilisent tous le même tas.
Il est de pratique courante de nos jours pour l'application et tous les fichiers DLL doivent être construits de façon à utiliser la version dynamique de la bibliothèque standard.
La seule réserve de ce qui précède est que si vous créez votre propre tas d'allouer de la mémoire à partir de ce segment. Mais c'est un domaine très spécialisé de la procédure ne le fait que dans de rares cas (et si vous comprenez suffisamment l'utiliser, alors vous ne serez pas dans la situation de poser cette question).
OriginalL'auteur Martin York