C# 装载机锁错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/56642/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Loader lock error
提问by Devdatta Tengshe
I am building on C++ dll, by writing code in C#.
我正在通过在 C# 中编写代码来构建 C++ dll。
I get an error, saying
我收到一个错误,说
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.
检测到 LoaderLock 消息:正在尝试在 OS Loader 锁内进行托管执行。不要尝试在 DllMain 或图像初始化函数中运行托管代码,因为这样做会导致应用程序挂起。
I tried seraching what this error exactly means, but I am drawing pointless articles, mostly saying that it's just a warning, and I should switch that off in Visual Studio. The other solutions seem to be due to ITunes, or this problem occurring when programming with DirectX. My problem is connected to neither.
我尝试搜索此错误的确切含义,但我正在绘制毫无意义的文章,主要是说这只是一个警告,我应该在 Visual Studio 中将其关闭。其他解决方案似乎是由于iTunes,或者使用DirectX编程时出现的这个问题。我的问题与两者都无关。
Can anybody explain, what this actually means?
任何人都可以解释一下,这实际上意味着什么?
回答by Hershi
The general idea of loader lock: The system runs the code in DllMain inside a lock (as in - synchronization lock). Therefore, running non-trivial code inside DllMain is "asking for a deadlock", as described here.
加载器锁的总体思路:系统在一个锁内运行DllMain中的代码(如in-同步锁)。因此,运行里面的DllMain不平凡的代码是“要求死锁”,描述在这里。
The question is, why are you trying to run code inside DllMain? Is it crucial that this code run inside the context of DllMain or can you spawn a new thread and run the code in it, and not wait for the code to finish execution inside DllMain?
问题是,为什么要尝试在 DllMain 中运行代码?这段代码在 DllMain 的上下文中运行是否至关重要,还是可以生成一个新线程并在其中运行代码,而不是等待代码在 DllMain 中完成执行?
I believe that the problem with manged code specifically, is that running managed code might involves loading the CLR and suchlike and there's no knowing what could happen there that would result in a deadlock... I would not heed the advice of "disable this warning" if I were you because most chances are you'll find your applications hangs unexpectedly under some scenarios.
我认为托管代码的具体问题在于,运行托管代码可能涉及加载 CLR 等,并且不知道那里会发生什么会导致死锁......我不会听从“禁用此警告”的建议" 如果我是你,因为大多数情况下你会发现你的应用程序在某些情况下意外挂起。
回答by ghiboz
you need to go to menu Debug -> Exceptions, open the Managed Debugging Assistants, find LoaderLock and uncheck
您需要转到菜单 Debug -> Exceptions,打开 Managed Debugging Assistants,找到 LoaderLock 并取消选中
回答by Rakshit Bakshi
This problem occurs because of the way in which the debugger in Visual Studio runs managed applications that use Microsoft Foundation Classes version 8.0 in one or more DLL files.
出现此问题的原因是 Visual Studio 中的调试器运行在一个或多个 DLL 文件中使用 Microsoft 基础类 8.0 版的托管应用程序的方式。
Have a thorough reading at: http://msdn.microsoft.com/en-us/library/aa290048(vs.71).aspx
仔细阅读:http: //msdn.microsoft.com/en-us/library/aa290048(vs.71).aspx
回答by Bhaskar Singh
Press ctr d+e Then Expend Managed Debugging Assistants Node. Then Unchecked the LoaderLock.
按 ctr d+e 然后扩展托管调试助手节点。然后取消选中 LoaderLock。
Hope this will help you.
希望这会帮助你。
回答by Stefan Wanitzek
I recently got this error while creating an instance of an COM-Object written in native code:
我最近在创建用本机代码编写的 COM 对象的实例时遇到了这个错误:
m_ComObject = Activator.CreateInstance(Type.GetTypeFromProgID("Fancy.McDancy"));
This led to the described error. A "LoaderLock was detected"-Exception was thrown.
这导致了所描述的错误。“检测到 LoaderLock” - 抛出异常。
I overcame this error by creating the object-instance in an extra thread:
我通过在一个额外的线程中创建对象实例来克服这个错误:
ThreadStart threadRef = new ThreadStart(delegate { m_ComObject = Activator.CreateInstance(Type.GetTypeFromProgID("Fancy.McDancy")); });
Thread myThread = new Thread(threadRef);
myThread.Start();
myThread.Join(); // for synchronization
回答by seva titov
UPDATE FOR .NET 4.0 AND MORE RECENT FRAMEWORKS
.NET 4.0 和更多最新框架的更新
This is an old question asked at the time of .Net 2.0, when support for mixed mode DLLs had serious initialization problems, prone to random deadlocks. As of .Net 4.0, the initialization of mixed mode DLLs has changed. Now there are two separate stages of initialization:
这是在 .Net 2.0 时提出的一个老问题,当时对混合模式 DLL 的支持存在严重的初始化问题,容易出现随机死锁。从 .Net 4.0 开始,混合模式 DLL 的初始化发生了变化。现在有两个独立的初始化阶段:
- Native initialization, called at the DLL's entry point, which includes native C++ run-time setup and execution of your DllMain method.
- Managed initialization, executed automatically by system loader.
- 本机初始化,在 DLL 的入口点调用,包括本机 C++ 运行时设置和 DllMain 方法的执行。
- 托管初始化,由系统加载程序自动执行。
Since step #2 is performed outside of the Loader Lock, there is no deadlocks. The details are described at Initialization of Mixed Assemblies.
由于第 2 步是在 Loader Lock 之外执行的,因此没有死锁。详细信息在混合程序集的初始化中描述。
To ensure your mixed mode assembly can be loaded from a native executable, the only thing you need to check is that DllMain method is declared as native code. #pragma unmanaged
could help here:
为确保您的混合模式程序集可以从本机可执行文件加载,您唯一需要检查的是 DllMain 方法是否声明为本机代码。#pragma unmanaged
可以在这里提供帮助:
#pragma unmanaged
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
... // your implementation here
}
It is also important that any code that DllMain might call directly or indirectly is also unmanaged. It makes sense to limit the type of functionality used by DllMain so you trace all code reachable from DllMain and ensure it is all compiled with #pragma unmanaged
.
同样重要的是,DllMain 可能直接或间接调用的任何代码也是非托管的。限制 DllMain 使用的功能类型是有意义的,因此您可以跟踪从 DllMain 可访问的所有代码并确保所有代码都使用#pragma unmanaged
.
Compiler helps a little by giving you warining C4747 if it detects that DllMain is not declared as unmanaged:
如果编译器检测到 DllMain 未声明为非托管,则编译器会通过警告 C4747 来帮助您:
1> Generating Code...
1>E:\src\mixedmodedll\dllmain.cpp : warning C4747: Calling managed 'DllMain': Managed code may not be run under loader lock, including the DLL entrypoint and calls reached from the DLL entrypoint
However compiler won't generate any warnings if DllMain indirectly calls some other managed function, so you need to ensure that never happens, otherwise your application could deadlock randomly.
但是,如果 DllMain 间接调用其他托管函数,编译器不会生成任何警告,因此您需要确保永远不会发生,否则您的应用程序可能会随机死锁。
回答by Menace
I'm building a C++ CLR DLL (MSVS2015) that has to make calls into an unmanaged DLL and define unmanaged code. I use #pragma managed and #pragma unmanaged to control what mode it is in for a given area of the code.
我正在构建一个 C++ CLR DLL (MSVS2015),它必须调用非托管 DLL 并定义非托管代码。我使用#pragma managed 和#pragma unmanaged 来控制给定代码区域的模式。
In my case I simply put #pragma unmanaged in front of my DllMain() and this solved the problem. It seemed to be thinking I wanted a managed version of DllMain().
就我而言,我只是将 #pragma unmanaged 放在我的 DllMain() 前面,这解决了问题。它似乎在想我想要一个 DllMain() 的托管版本。
回答by Jog Dan
kindly remind those VS2017 usersthat you need to disable "exception helper" instead of "exception assistant"(before VS2017) to prevent from loader lock error, which setting path is Debug->Exception. Just ran int to this problem and wasted 2 hours searching for solutions...
温馨提醒那些VS2017用户,您需要禁用“异常助手”而不是“异常助手”(VS2017之前)以防止加载器锁定错误,其设置路径为Debug->Exception。刚刚遇到这个问题并浪费了2个小时寻找解决方案......
回答by Jimmy
The setting path in my visual studio 2017 instance is Debug -> Windows -> Exception Settings . The exception settings "window" showed up in the bottom tab group (as opposed to a separate window), took me a while to notice it. Search for "loader".
我的 Visual Studio 2017 实例中的设置路径是 Debug -> Windows -> Exception Settings 。异常设置“窗口”显示在底部选项卡组(而不是单独的窗口)中,我花了一段时间才注意到它。搜索“装载机”。