程序终止时发生LoaderLock错误
我最近将.NET NLog日志记录组件集成到我们的应用程序中,这些应用程序完全是在非托管代码(在Visual Studio 6中编译的C++和VB6组件)开发的。我们有一堆C++应用程序通过COM接口与NLog交谈。程序终止时发生LoaderLock错误
目前一切正常,但我注意到在程序终止期间弹出以下消息(如果在VS6中调试C++组件,则在输出窗口中;如果通过VS 2005调试NLog,则在IDE中作为提示) :
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引用的释放(我保持到NLOG对象的引用在我的C++类之一避免每次都要实例化和释放),这会导致此警告弹出。
我的问题:这是安全的忽略?如果不是,什么是一个好的解决方法? (我能想到的最好的办法是实例化对该NLog对象的引用,并在每次我要写入日志文件时释放它;不是最优雅的解决方案)
这是绝对不安全的忽略此消息。如果你点击这个消息,你几乎肯定会创建一个真正的加载程序锁定策略违规。这是一个非常严重的错误,可能会导致程序中出现不可预知的行为(包括死锁)。
避免这种情况的最佳方法是不直接或间接访问任何其他.Net对象/函数。对于你的情况,最好使用不同的缓存策略。也许创建一个引用计数对象来保存.Net引用。这样,在DllMain被调用卸载之前,对象将被释放(在所有对象被销毁之前,dll不能被卸载)。
不要忽视。我在启动使用非托管C++ DLL的C#应用程序时遇到LoaderLock问题。在这种情况下,某些DLL代码(从Linux移植)具有在加载期间在初始化时访问文件的静态内容。一旦静态清理完毕,LoaderLock问题就解决了。以类似的方式,如果您有清理期间访问文件的C/C++静态内容,这可能会对LoaderLock有所贡献。
从非托管C++ DLL访问文件如何导致托管C#代码执行? – 2009-04-23 11:29:40