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

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

Я получаю сообщение об ошибке, говоря

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

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

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

Ответ 1

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

http://goo.gl/TGAHV

Ответ 2

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

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

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

Ответ 3

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

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

Ответ 4

ОБНОВЛЕНИЕ ДЛЯ .NET 4.0 И БОЛЬШЕ ПОСЛЕДНИЕ РАМКИ

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

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

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

Ответ 5

Недавно я получил эту ошибку при создании экземпляра 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

Ответ 6

Эта проблема возникает из-за того, как отладчик в Visual Studio запускает управляемые приложения, использующие Microsoft Foundation Classes версии 8.0 в одном или нескольких DLL файлах.

Прочитайте следующее: http://msdn.microsoft.com/en-us/library/aa290048(vs.71).aspx

Ответ 7

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

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