【问题标题】:Loader lock error加载程序锁定错误
【发布时间】:2010-09-08 13:41:22
【问题描述】:

我在 C++ dll 上构建,用 C# 编写代码。

我得到一个错误,说

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

我尝试搜索此错误的确切含义,但我在绘制毫无意义的文章,主要是说这只是一个警告,我应该在 Visual Studio 中将其关闭。 其他解决方案似乎是由于 iTunes,或者使用 DirectX 编程时出现的这个问题。我的问题与这两个都没有关系。

谁能解释一下,这到底是什么意思?

【问题讨论】:

  • 我和你有同感,我遇到了同样的问题,最让我惊讶的是:我的 dll 甚至不是托管代码,那么为什么/如何应该在(不存在的)上使用托管代码) DllMain??
  • 我在尝试以调试模式查看数据集的内容时收到此警告。我正在使用 c#,它发生在常规的 windows 窗体中。
  • 由于您无法找出原因(正如您在最佳答案中评论的那样),我怀疑您正在加载的 dll 正在犯罪。

标签: c# loaderlock


【解决方案1】:

loader锁的大致思路: 系统在锁内运行 DllMain 中的代码(如同步锁)。因此,如here 所述,在 DllMain 中运行重要代码是“要求死锁”。

问题是,你为什么要在 DllMain 中运行代码?这段代码在 DllMain 的上下文中运行是否至关重要,或者您是否可以生成一个新线程并在其中运行代码,而不是等待代码在 DllMain 中完成执行?

我认为托管代码的具体问题在于,运行托管代码可能涉及加载 CLR 等,并且不知道那里会发生什么会导致死锁......我不会听从“如果我是您,请禁用此警告”,因为您很可能会发现您的应用程序在某些情况下意外挂起。

【讨论】:

  • 我正在开发 Direct3D 应用程序。这是一个EXE。但是,我仍然看到这个错误。任何想法如何最好地解决这个问题?
【解决方案2】:

你需要进入菜单Debug -> Exceptions,打开Managed Debugging Assistants,找到LoaderLock并取消勾选

【讨论】:

  • 是的,这是关闭警告的方法;但即使在 2 年后我还没有弄清楚它发生的确切原因。
  • 这发生在我在 VS 2012 中打开一个旧项目
  • 我和你在一起@Kohan 我还打开了一个较旧的项目并得到了错误。我已禁用该异常,但想了解可以采取哪些措施来防止这种情况发生。
  • 如果我将项目作为本地调试运行,默认情况下所有异常(全部重置),调试窗口显示 schemas.microsoft.com/CLR/2004/10/mda"> VS 然后在 CTOR 序列期间呈现多个断点。关闭 LoaderLock 设置没有帮助。对我来说,我必须勾选顶级 MDA 选项(对于 ALL MDA)然后取消勾选顶级选项(对于没有 MDA),然后构建+运行。这对我的同事不起作用。
  • 想要分享 VS2015 的更新,你现在需要去Debug->Windows->Exception Settings。其余同Managed Debugging Assistants \ LoaderLock
【解决方案3】:

出现此问题的原因在于 Visual Studio 中的调试器运行托管应用程序的方式,这些应用程序在一个或多个 DLL 文件中使用 Microsoft Foundation Classes 8.0 版。

详细阅读:http://msdn.microsoft.com/en-us/library/aa290048(vs.71).aspx

【讨论】:

    【解决方案4】:

    按 ctr d+e 然后展开托管调试助手节点。然后取消选中LoaderLock。

    希望这会对你有所帮助。

    【讨论】:

    • 快捷方式实际上取决于您在首次运行时指定使用的配置。 C# 快捷方式布局为 (Ctrl+D, E)。 (您也可以在选项->环境->键盘中为此功能分配任何组合键。)
    【解决方案5】:

    我最近在创建用本机代码编写的 COM-Object 实例时遇到了这个错误:

    m_ComObject = Activator.CreateInstance(Type.GetTypeFromProgID("Fancy.McDancy"));
    

    这导致了所描述的错误。 “检测到 LoaderLock”-抛出异常。

    我通过在一个额外的线程中创建对象实例克服了这个错误:

    ThreadStart threadRef = new ThreadStart(delegate { m_ComObject = Activator.CreateInstance(Type.GetTypeFromProgID("Fancy.McDancy")); });
    Thread myThread = new Thread(threadRef);
    
    myThread.Start();
    myThread.Join(); // for synchronization
    

    【讨论】:

    • Remotable objects (MarshalByRefObject) 可能会发生错误,并且此解决方案不适用于那些。
    【解决方案6】:

    .NET 4.0 和更多最新框架的更新

    这是 .Net 2.0 时提出的一个老问题,当时对混合模式 DLL 的支持存在严重的初始化问题,容易出现随机死锁。从 .Net 4.0 开始,混合模式 DLL 的初始化发生了变化。现在有两个独立的初始化阶段:

    1. 本机初始化,在 DLL 的入口点调用,包括本机 C++ 运行时设置和 DllMain 方法的执行。
    2. 托管初始化,由系统加载程序自动执行。

    由于第 2 步是在 Loader Lock 之外执行的,因此没有死锁。详细信息在Initialization of Mixed Assemblies 中进行了描述。

    为确保您的混合模式程序集可以从本机可执行文件加载,您唯一需要检查的是 DllMain 方法是否声明为本机代码。 #pragma unmanaged 可以在这里提供帮助:

    #pragma unmanaged
    
    BOOL APIENTRY DllMain(HMODULE hModule,
        DWORD  ul_reason_for_call,
        LPVOID lpReserved
        )
    {
        ... // your implementation here
    }
    

    同样重要的是,DllMain 可能直接或间接调用的任何代码也是非托管的。限制 DllMain 使用的功能类型是有意义的,因此您可以跟踪从 DllMain 可访问的所有代码,并确保所有代码都使用#pragma 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
    

    但是,如果 DllMain 间接调用其他托管函数,编译器不会生成任何警告,因此您需要确保永远不会发生,否则您的应用程序可能会随机死锁。

    【讨论】:

      【解决方案7】:

      我正在构建一个 C++ CLR DLL (MSVS2015),它必须调用非托管 DLL 并定义非托管代码。我使用#pragma managed 和#pragma unmanaged 来控制给定代码区域的模式。

      在我的例子中,我只是将#pragma unmanaged 放在我的 DllMain() 前面,这就解决了问题。 它似乎在想我想要一个 DllMain() 的托管版本。

      【讨论】:

        【解决方案8】:

        请提醒那些VS2017用户,您需要禁用“异常助手”而不是“异常助手”(VS2017之前)以防止from loader lock error,设置路径为Debug->Exception。刚刚遇到这个问题,浪费了 2 个小时寻找解决方案......

        【讨论】:

        • 我在“调试”下没有“异常”。我有 VS2017 社区 15.8.4
        • @Alex,检查 Debug-->Windows-->Exception Settings,或者按 Ctrl+Alt+E
        【解决方案9】:

        我的 Visual Studio 2017 实例中的设置路径是 Debug -> Windows -> Exception Settings 。例外设置“窗口”显示在底部选项卡组中(而不是单独的窗口),我花了一段时间才注意到它。搜索“加载器”。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-20
          相关资源
          最近更新 更多