2009-01-29 7 views
2

J'ai récemment intégré le composant de journalisation .NET NLog dans l'une de nos applications, développée uniquement en code non managé (composants C++ et VB6 compilés dans Visual Studio 6). Nous avons un tas d'applications C++ parlant à NLog via une interface COM. Tout fonctionne très bien pour le moment mais je remarque que le message suivant apparaît (dans la fenêtre de sortie si déboguer le composant C++ dans VS6, comme invite dans l'EDI si déboguer NLog via VS 2005) pendant la terminaison du programme :Erreur LoaderLock à la fin du programme

LoaderLock a été détecté message: Tentative d'exécution géré à l'intérieur OS verrouillage Loader. N'essayez pas d'exécuter le code managé à l'intérieur d'une fonction d'initialisation DllMain ou image car cela peut entraîner le blocage de l'application.

Le DllMain est la suivante:

extern "C" 
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) 
{ 
    if (dwReason == DLL_PROCESS_ATTACH) 
    { 
     _Module.Init(ObjectMap, hInstance); 
     DisableThreadLibraryCalls(hInstance); 
    } 
    else if (dwReason == DLL_PROCESS_DETACH) 
     _Module.Term(); 
    return TRUE; // ok 
} 

Je pense que _Module.Term(); comprend maintenant la libération de quelques références .NET (je garde une référence à un objet NLog dans un de mes classes C++ à évitez d'avoir à instancier et relâcher chaque fois) ce qui fait apparaître cet avertissement.

Ma question: est-ce sûr à ignorer? Si ce n'est pas le cas, qu'est-ce qu'une bonne solution de contournement? (le mieux que je puisse penser est d'instancier une référence à cet objet NLog et de le relâcher chaque fois que je veux écrire dans le fichier journal ... pas la plus élégante des solutions)

Répondre

6

Il n'est certainement pas sûr de ignorez ce message. Si vous répondez à ce message, vous avez presque certainement créé une violation réelle de la politique de verrouillage du chargeur. Ceci est une erreur très sérieuse et peut entraîner un comportement imprévisible dans un programme (y compris un blocage).

La meilleure façon d'éviter cela est de ne pas accéder à d'autres objets/fonctions .Net directement ou indirectement à l'intérieur de la DLL principale. Pour votre cas, il est probablement préférable d'utiliser une autre stratégie de cache. Peut-être créer un objet compté ref pour contenir la référence .Net. De cette façon, l'objet sera libéré avant que DllMain soit appelé pour le déchargement (la DLL ne peut pas être déchargée tant que tous vos objets ne sont pas détruits).

2

Ne pas ignorer. J'ai eu un problème LoaderLock au démarrage d'une application C# qui utilisait une DLL C++ non managée. Dans ce cas, certains codes DLL (portés depuis Linux) avaient des statistiques qui accédaient aux fichiers à l'initialisation pendant le chargement. Une fois les statistiques nettoyées, le problème LoaderLock a été corrigé. De la même manière, si vous avez des statistiques C/C++ qui accèdent aux fichiers pendant le nettoyage, cela pourrait contribuer à votre LoaderLock.

+0

Comment l'accès aux fichiers à partir d'une DLL C++ non managée provoque l'exécution du code C# managé? –

+0

Le code C# s'exécute en premier et appelle la méthode exportée par la DLL non managée. La première fois que la méthode exportée est appelée, la DLL est chargée par .Net. C'est pendant ce chargement de la DLL non managée que la DLL ne peut pas accéder aux fichiers. Mais, les variables statiques dans la DLL sont initialisées lors du chargement de la DLL. Et, si leur initialisation accède aux fichiers, une erreur LoaderLock peut en résulter. L'erreur semble être levée par le code C# qui a appelé la méthode DLL qui a chargé la DLL. –

Questions connexes