2009-12-14 7 views
4

J'écris une DLL qui a besoin d'appeler dynamiquement une DLL séparée plusieurs fois. Je voudrais garder l'appelé chargé et juste le décharger quand ma DLL est déchargée. Mais selon Microsoft, c'est un bad idea.Pourquoi ne pas appeler FreeLibrary depuis la fonction de point d'entrée?

La fonction de point d'entrée doit seulement effectuer des tâches d'initialisation simples et ne doit pas appeler d'autres fonctions de chargement ou de cessation d'emploi DLL . Pour exemple, dans la fonction de point d'entrée, vous ne devez pas directement ou indirectement appeler la fonction LoadLibrary ou la fonction LoadLibraryEx . De plus, vous ne devez pas appeler la fonction FreeLibrary lorsque le processus est se terminant.

Voici le code incriminé. Quelqu'un peut-il expliquer pourquoi je ne devrais pas appeler LoadLibrary et FreeLibrary depuis le point d'entrée de ma DLL?

BOOL APIENTRY DllMain(HANDLE hModule, 
         DWORD ul_reason_for_call, 
         LPVOID lpReserved 
        ) 
{ 
switch (ul_reason_for_call) { 
    case DLL_PROCESS_DETACH : 
      if (hLogLib != NULL) FreeLibrary(hLogLib); 
      break; 
    } 
    return TRUE; 
} 
+0

Comment savez-vous que la DLL n'a pas déjà été déchargée? –

+0

@Anon: Je ne le fais pas. En fait, je ne sais pas si c'était même chargé. Mais s'il a été chargé et n'a pas déjà été déchargé, je veux le décharger. –

+0

Des sons semblables à vous devraient être liés statiquement à l'autre DLL, plutôt que d'essayer de le charger dynamiquement. –

Répondre

4

Je crois que j'ai trouvé the answer.

La fonction point d'entrée doit effectuer seulement simple initialisation ou tâches de terminaison. Il ne doit pas appeler la fonction LoadLibrary ou LoadLibraryEx (ou une fonction qui appelle ces fonctions), car cela peut créer des boucles de dépendance dans l'ordre de chargement DLL. Cela peut entraîner l'utilisation d'une DLL avant que le système ait exécuté son code d'initialisation. De même, la fonction point d'entrée ne doit pas appeler la fonction FreeLibrary (ou une fonction qui appelle FreeLibrary) pendant la fin du processus, car cela peut entraîner une DLL utilisé après que le système a exécuté son code de terminaison .

+0

Il est encore obscur, ce qui utiliserait le code de la bibliothèque après qu'il a été terminé et libéré? Je suppose que l'on libère seulement la bibliothèque que l'on a chargée auparavant ... et que le code de terminaison s'exécute seulement si cet appel de FreeLibrary libère la dernière référence à cette DLL. –

2

Vous ne pouvez pas appeler LoadLibrary à partir de votre point d'entrée parce que la fonction DllMain passe à l'intérieur d'un verrou de chargeur OS et toute tentative de réacquérir que le verrouillage du chargeur (par exemple, en appelant LoadLibrary) entraînera une impasse.

+1

Mais qu'en est-il de FreeLibrary? Quel genre de problèmes cela pourrait-il causer? –

1

Ne pas faire quoi que ce soit de conséquence intérieur de DLLMain. Sérieusement. Appeler FreeLibrary est encore pire car il ne sera que parfois deadlock, s'il arrive que votre free décrémente le refcount à zéro et que la librairie est réellement libérée.