我最近将.NET NLog日志组件集成到我们的应用程序中,该应用程序纯粹是用非托管代码(在Visual 6中编译的C++和VB6组件)开发的。我们有一堆C++应用程序通过COM接口与NLog通信。
目前一切正常,但我确实注意到,在程序终止期间,会弹出以下消息(如果在VS6中调试VS6组件,则在输出窗口中;在IDE通过VS 2005调试NLog时作为提示符):
检测到
LoaderLock消息:尝试在OS Loader锁中执行托管程序。不要试图在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对象的引用,并在每次我想要将最优雅的解决方案写入日志file...not时释放它)
发布于 2009-01-29 04:57:35
忽略这条信息肯定是不安全的。如果您命中此消息,几乎可以肯定您已经创建了一个真正的加载程序锁策略违规。这是一个非常严重的错误,可能导致程序中不可预测的行为(包括死锁)。
避免这种情况的最好方法是不直接或间接地访问DLL main中的任何其他.Net对象/函数。对于您的情况,最好使用不同的缓存策略。也许可以创建一个ref计数对象来保存.Net引用。这样,在调用DllMain卸载之前将释放该对象(在销毁所有对象之前不能卸载dll )。
发布于 2009-01-29 06:24:43
别忽视。我在启动一个使用非托管的LoaderLock DLL的C#应用程序时遇到了C++问题。在本例中,一些DLL代码(从Linux移植)具有静态特性,在加载期间访问初始化时的文件。一旦静力学被清理,LoaderLock问题就被解决了。类似地,如果您有C/C++静态代码,在清理过程中访问文件,这可能有助于您的LoaderLock。
https://stackoverflow.com/questions/490430
复制相似问题