Ошибка блокировки загрузчика


95

Я строю на C ++ dll, написав код на C #.

Я получаю сообщение об ошибке

LoaderLock был обнаружен. Сообщение: Попытка управляемого выполнения внутри блокировки загрузчика ОС. Не пытайтесь запускать управляемый код внутри функции инициализации DllMain или изображения, поскольку это может привести к зависанию приложения.

Я попытался выяснить, что именно означает эта ошибка, но рисую бессмысленные статьи, в основном говоря, что это всего лишь предупреждение, и я должен отключить его в Visual Studio. Другие решения, похоже, связаны с ITunes или этой проблемой, возникающей при программировании с помощью DirectX. Моя проблема ни с чем не связана.

Кто-нибудь может объяснить, что это на самом деле означает?


Я чувствую, что у меня такая же проблема, и что меня больше всего удивляет: моя dll даже не является управляемым кодом, так почему / как предполагается использовать управляемый код в (несуществующей) DllMain ??
Сэм

Я получил это предупреждение при попытке просмотреть содержимое набора данных в режиме отладки. Я использую C #, это произошло в обычной форме Windows.
Soenhay

Поскольку вы не можете выяснить причину (как вы прокомментировали в верхнем ответе), я подозреваю, что вы загружаете DLL, которая совершает преступление.
John Thoits

Ответы:


70

вам нужно перейти в меню Отладка -> Исключения, открыть помощников по управляемой отладке, найти LoaderLock и снять флажок

http://goo.gl/TGAHV


21
да, это способ отключить предупреждение; Но даже через 2 года я так и не понял, почему это происходит.
Devdatta Tengshe

2
Это случилось со мной, когда я открывал старый проект в VS 2012
4imble,

1
Я с вами @Kohan Я также открыл более старый проект и получил ошибку. Я отключил исключение, но хотел бы понять, что можно сделать, чтобы этого избежать.
Pimenta

1
Если я запускаю проект как отладку в собственном коде со всеми исключениями по умолчанию (сбросить все), в окне отладки отображается <mda: msg xmlns: mda = " schemas.microsoft.com/CLR/2004/10/mda "> <! - - Попытка управляемого выполнения внутри блокировки загрузчика ОС .... и т. Д. -> <mda: loaderLockMsg break = "true" /> </ mda: msg> Затем VS представляет несколько точек останова во время последовательности CTOR. Отключение параметра LoaderLock не помогает. Что касается меня, мне пришлось отметить верхнюю опцию MDA (для ВСЕХ MDA), затем снять отметку с опции верхнего уровня (без MDA), затем построить + запустить. У моего коллеги это не сработало.
GilesDMiddleton

17
Хотел поделиться обновлением в VS2015, теперь вам нужно перейти на Debug->Windows->Exception Settings. В остальном то же самое сManaged Debugging Assistants \ LoaderLock
jxramos 03

52

Общая идея блокировки загрузчика: система запускает код в DllMain внутри блокировки (как в блокировке синхронизации). Следовательно, выполнение нетривиального кода внутри DllMain «запрашивает взаимоблокировку», как описано здесь .

Вопрос в том, почему вы пытаетесь запустить код внутри DllMain? Важно ли, чтобы этот код выполнялся в контексте DllMain, или вы можете создать новый поток и запустить в нем код, а не ждать, пока код завершит выполнение внутри DllMain?

Я считаю, что проблема с управляемым кодом, в частности, заключается в том, что запуск управляемого кода может включать загрузку CLR и тому подобное, и неизвестно, что там может произойти, что приведет к тупиковой ситуации ... Я бы не прислушался к совету «отключить это предупреждение» "Если бы я был вами, потому что, скорее всего, вы обнаружите, что ваши приложения неожиданно зависают при некоторых сценариях.


4
Я работаю над приложением Direct3D. Это EXE. Однако я все еще вижу эту ошибку. Есть идеи, как это лучше всего исправить?
Agnel Kurian

18

ОБНОВЛЕНИЕ ДЛЯ .NET 4.0 И БОЛЕЕ НЕДАВНИХ Фреймворков

Это старый вопрос, который задавали во времена .Net 2.0, когда поддержка библиотек DLL смешанного режима имела серьезные проблемы с инициализацией, склонные к случайным тупикам. Начиная с .Net 4.0, инициализация библиотек DLL смешанного режима изменилась. Теперь есть два отдельных этапа инициализации:

  1. Собственная инициализация, вызываемая в точке входа библиотеки DLL, которая включает встроенную настройку времени выполнения C ++ и выполнение вашего метода DllMain.
  2. Управляемая инициализация, автоматически выполняемая загрузчиком системы.

Поскольку шаг №2 выполняется вне Loader Lock, взаимоблокировок нет. Подробности описаны в разделе «Инициализация смешанных сборок» .

Чтобы гарантировать, что ваша сборка в смешанном режиме может быть загружена из собственного исполняемого файла, единственное, что вам нужно проверить, - это то, что метод 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 .

Компилятор немного помогает, предупреждая C4747, если он обнаруживает, что DllMain не объявлен как неуправляемый:

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 косвенно вызывает какую-либо другую управляемую функцию, поэтому вам нужно убедиться, что этого никогда не произойдет, иначе ваше приложение может случайно заблокироваться.


6

Нажмите ctr d + e, затем выберите узел помощников по управляемой отладке. Затем снял флажок с LoaderLock.

Надеюсь, что это поможет вам.


Ярлык - alt + d + x
Нараян

3
Ярлык фактически зависит от конфигурации, которую вы указали для использования при первом запуске. Макет ярлыка C # (Ctrl + D, E). (Также вы можете назначить любую комбинацию клавиш для этой функции в Параметры-> Среда-> Клавиатура.)
Adam LS

6

любезно напомните пользователям VS2017, что вам необходимо отключить « помощник по исключениям » вместо « помощника по исключениям » (до VS2017), чтобы предотвратить ошибку блокировки загрузчика, путь настройки которой - Debug-> Exception . Просто побежал к этой проблеме и потратил 2 часа на поиск решений ...


У меня нет «Исключения» в разделе «Отладка». У меня есть сообщество VS2017 15.8.4
Alex

@Alex, проверьте Debug -> Windows -> Exception Settings или нажмите Ctrl + Alt + E
mistika

4

Недавно я получил эту ошибку при создании экземпляра COM-объекта, написанного в машинном коде:

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 (MarshalByRefObject), и это решение для них не работает.
Матье

3

Я создаю C ++ CLR DLL (MSVS2015), которая должна вызывать неуправляемую DLL и определять неуправляемый код. Я использую #pragma managed и #pragma unmanaged, чтобы контролировать, в каком режиме он находится для данной области кода.

В моем случае я просто поставил #pragma unmanaged перед DllMain (), и это решило проблему. Казалось, что мне нужна управляемая версия DllMain ().



2

Путь настройки в моем экземпляре Visual Studio 2017: Отладка -> Windows -> Параметры исключений. «Окно» настроек исключения появилось в нижней группе вкладок (в отличие от отдельного окна), мне потребовалось время, чтобы это заметить. Ищите "загрузчик".

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.