Поделиться через


Помощник по отладке управляемого кода loaderLock

Примечание.

Эта статья относится к .NET Framework. Он не применяется к более новым реализациям .NET, включая .NET 6 и более поздние версии.

Помощник по отладке управляемого кода loaderLock (MDA) определяет попытки выполнения управляемого кода в потоке, который удерживает блокировку загрузчика операционной системы Microsoft Windows. Любое подобное выполнение кода недопустимо, поскольку оно может привести к взаимоблокировке и использованию библиотек DLL до того, как они будут инициализированы загрузчиком операционной системы.

Симптомы

Наиболее распространенная ошибка при выполнении кода во время блокировки загрузчика операционной системы состоит во взаимоблокировке потоков при попытке вызова других функций Win32, которым также требуется блокировка загрузчика. Примерами таких функций являются LoadLibrary, GetProcAddress, FreeLibrary и GetModuleHandle. Приложение не может вызывать эти функции напрямую; общеязыковая среда выполнения (CLR) может вызывать эти функции в результате вызовов более высокого уровня, например Load или в качестве первого вызова метода неуправляемого кода.

Взаимоблокировка также может возникнуть, если поток ожидает запуска или завершения другого потока. При запуске или завершении потока этот поток должен получить блокировку загрузчика операционной системы, чтобы передать события в связанные библиотеки DLL.

Наконец, в некоторых случаях вызовы библиотек DLL могут происходить до того, как эти библиотеки были инициализированы загрузчиком операционной системы. В отличие от сбоев по причине взаимоблокировки, которые можно определить, просмотрев стеки всех потоков, включенных во взаимоблокировку, выявить использование DLL-библиотек, которые не были инициализированы, без помощника по отладке управляемого кода очень трудно.

Причина

Смешанные сборки с управляемым и неуправляемым кодом C++ для .NET Framework версий 1.0 и 1.1 обычно пытаются выполнять управляемый код во время блокировки загрузчика, если не предпринималось специальных действий, например связывания с помощью /NOENTRY.

Смешанные сборки с управляемым и неуправляемым кодом C++ для .NET Framework версии 2.0 менее подвержены влиянию этих проблем, но риск все равно сохраняется, так как приложения используют неуправляемые библиотеки DLL, которые нарушают правила операционной системы. Например, если точка входа неуправляемой библиотеки DLL DllMain вызывает CoCreateInstance для получения управляемого объекта, который был открыт для COM, то результатом такой операции станет попытка выполнения управляемого кода во время блокировки загрузчика. Дополнительные сведения о проблеме блокировки загрузчика в платформе .NET Framework версии 2.0 и более поздней см. в разделе Инициализация смешанных сборок.

Разрешение

В Visual C++ .NET 2002 и Visual C++ .NET 2003 библиотеки DLL, скомпилированные с использованием параметра /clr, могут случайным образом создать ситуацию взаимоблокировки при загрузке. Подобная ситуация называется проблемой загрузки смешанных библиотек DLL или проблемой блокировки загрузчика. В Visual C++ 2005 и более поздней версии почти все недетерминированные ситуации при загрузке смешанных библиотек DLL исключены. Однако остаются несколько определенных случаев, в которых может произойти блокировка загрузчика. Подробные сведения о причинах оставшихся проблем с блокировкой загрузчика и методах их решения см. в разделе Инициализация смешанных сборок. Если определить проблему с блокировщиком с помощью этого раздела не удается, следует изучить стек потока, чтобы понять, почему происходит блокировка загрузчика и как решить эту проблему. Просмотрите трассировку стека для потока, который вызвал помощник по отладке управляемого кода. Этот поток пытается выполнить недопустимый вызов управляемого кода во время блокировки загрузчика операционной системы. Вы должны увидеть в стеке точку входа DllMain для библиотеки DLL или эквивалентную точку входа. Правила операционной системы сильно ограничивают действия, которые допустимы в этой точке входа. Эти правила исключают любое выполнение управляемого кода.

Влияние на среду выполнения

Как правило, блокировка возникает для нескольких потоков внутри процесса. Один из этих потоков, скорее всего, будет отвечать за сборку мусора, поэтому взаимоблокировка может оказать значительное влияние на весь процесс. Кроме того, это приведет к невозможности выполнения дополнительных операций, требующих блокировки загрузчика операционной системы, таких как загрузка и выгрузка сборок или библиотек DLL и запуск или остановка потоков.

В некоторых нетипичных случаях также возможно нарушение прав доступа или похожие проблемы в библиотеках DLL, которые вызываются до их инициализации.

Выходные данные

Помощник по отладке управляемого кода сообщает о попытке недопустимого выполнения управляемого кода. Изучите стек потока, чтобы понять, почему происходит блокировка загрузчика и как решить эту проблему.

Настройка

<mdaConfig>
  <assistants>
    <loaderLock/>
  </assistants>
</mdaConfig>

См. также