我最近将 .NET NLog 日志记录组件集成到我们的一个应用程序中,该应用程序完全使用非托管代码(在 Visual Studio 6 中编译的 C++ 和 VB6 组件)开发。我们有一堆 C++ 应用程序通过 COM 接口(interface)与 NLog 对话。
目前一切正常,但我确实注意到在程序终止期间弹出以下消息(如果在 VS6 中调试 C++ 组件,则在输出窗口中;如果通过 VS 2005 调试 NLog,则作为 IDE 中的提示):
LoaderLock was detected Message: Attempting managed execution inside OS Loader lock. Do not attempt to run managed code inside a DllMain or image initialization function since doing so can cause the application to hang.
DllMain如下:
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
}
我的猜测是 _Module.Term();
现在包括释放一些 .NET 引用(我在我的一个 C++ 类中保留对 NLog 对象的引用以避免必须实例化并每次释放)导致弹出此警告。
我的问题:忽略这个安全吗?如果不是,什么是好的解决方法? (我能想到的最好的办法是实例化对该 NLog 对象的引用,并在每次我想写入日志文件时释放它……这不是最优雅的解决方案)
最佳答案
忽略此消息绝对是不安全的。如果您看到此消息,几乎可以肯定您已经创建了一个真正的加载程序锁定策略违规。这是一个非常严重的错误,可能会导致程序出现不可预知的行为(包括死锁)。
避免这种情况的最佳方法是不要在 DLL main 中直接或间接访问任何其他 .Net 对象/函数。对于您的情况,最好使用不同的缓存策略。也许创建一个引用计数对象来保存 .Net 引用。这样,对象将在调用 DllMain 进行卸载之前被释放(在销毁所有对象之前无法卸载 dll)。
关于.net - 程序终止时出现 LoaderLock 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/490430/