程序终止时LoaderLock错误

时间:2009-01-29 03:55:09

标签: .net c++ unmanaged loaderlock

我最近将.NET NLog日志记录组件集成到我们的一个应用程序中,这些应用程序纯粹是在非托管代码(在Visual Studio 6中编译的C ++和VB6组件)中开发的。我们有一堆C ++应用程序通过COM接口与NLog通信。

目前一切正常但我注意到在程序终止期间弹出以下消息(在输出窗口中调试VS6中的C ++组件;如果在IDE中调试NLog,则通过VS 2005调试NLog):

  

检测到LoaderLock消息:   在OS中尝试托管执行   装载机锁。不要试图跑   DllMain或图像中的托管代码   初始化函数,因为这样做   可以导致应用程序挂起。

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对象的引用,并在每次要写入日志文件时释放它...而不是最优雅的解决方案)

2 个答案:

答案 0 :(得分:6)

忽略此消息绝对不安全。如果您点击此消息,您几乎肯定会创建一个真正的加载程序锁定策略违规。这是一个非常严重的错误,可能会导致程序中出现不可预测的行为(包括死锁)。

避免这种情况的最佳方法是不直接或间接访问DLL main中的任何其他.Net对象/函数。对于您的情况,最好使用不同的缓存策略。也许创建一个ref计数对象来保存.Net引用。这样,在调用DllMain进行卸载之前将释放该对象(在销毁所有对象之前无法卸载dll)。

答案 1 :(得分:2)

不要忽视。我在启动使用非托管C ++ DLL的C#应用​​程序时遇到了LoaderLock问题。在这种情况下,一些DLL代码(从Linux移植)具有在加载期间初始化时访问文件的静态。清理完静态后,修复了LoaderLock问题。以类似的方式,如果你有清理过程中访问文件的C / C ++静态,这可能会对你的LoaderLock有所帮助。