Erro de bloqueio do carregador


95

Estou construindo em dll C ++, escrevendo código em C #.

Recebo um erro, dizendo

LoaderLock foi detectado Mensagem: Tentativa de execução gerenciada dentro do bloqueio do carregador do SO. Não tente executar código gerenciado dentro de um DllMain ou função de inicialização de imagem, pois isso pode causar o travamento do aplicativo.

Eu tentei pesquisar o que esse erro significa exatamente, mas estou desenhando artigos inúteis, a maioria dizendo que é apenas um aviso, e devo desligar isso no Visual Studio. As outras soluções parecem ser devido ao iTunes, ou este problema que ocorre durante a programação com DirectX. Meu problema não está relacionado a nenhum deles.

Alguém pode explicar o que isso realmente significa?


Sinto que estou com o mesmo problema, e o que mais me surpreende: minha dll nem mesmo é código gerenciado, então por que / como ela deve usar código gerenciado no (inexistente) DllMain ??
Sam

Recebi este aviso ao tentar visualizar o conteúdo de um conjunto de dados no modo de depuração. Estou usando o c #, aconteceu em um formulário normal do Windows.
Soenhay

Como você não consegue descobrir a causa (como você comentou na primeira resposta), suspeito que há uma dll que você está carregando que está cometendo o crime.
John Thoits

Respostas:


70

você precisa ir para o menu Depurar -> Exceções, abrir os Assistentes de depuração gerenciados, encontrar LoaderLock e desmarcar

http://goo.gl/TGAHV


21
sim, esta é a forma de desligar o aviso; Mas mesmo depois de 2 anos eu não descobri exatamente porque isso estava acontecendo.
Devdatta Tengshe

2
Isso aconteceu comigo abrindo um projeto antigo no VS 2012
4imble

1
Estou com você @Kohan. Também abri um projeto antigo e recebi o erro. Desativei a exceção, mas gostaria de entender o que pode ser feito para evitar isso.
Pimenta

1
Se eu executar o projeto como depuração nativa, com todas as exceções no padrão (redefinir tudo), a janela de depuração mostra <mda: msg xmlns: mda = " schemas.microsoft.com/CLR/2004/10/mda "> <! - - Tentativa de execução gerenciada dentro do bloqueio do OS Loader .... etc -> <mda: loaderLockMsg break = "true" /> </ mda: msg> VS então apresenta vários pontos de interrupção durante a sequência CTOR. Desativar a configuração LoaderLock não ajuda. Para mim, tive que marcar a opção de MDA superior (para TODOS os MDA), desmarcar a opção de nível superior (para nenhum MDA) e, em seguida, construir + executar. Isso não funcionou para meu colega.
GilesDMiddleton

17
Desejava compartilhar uma atualização no VS2015, agora você precisa ir para Debug->Windows->Exception Settings. O resto é o mesmo comManaged Debugging Assistants \ LoaderLock
jxramos

52

A ideia geral do bloqueio do carregador: O sistema executa o código em DllMain dentro de um bloqueio (como em - bloqueio de sincronização). Portanto, executar um código não trivial dentro do DllMain é "pedir um deadlock", conforme descrito aqui .

A questão é: por que você está tentando executar o código dentro do DllMain? É crucial que esse código seja executado dentro do contexto de DllMain ou você pode gerar um novo thread e executar o código nele, e não esperar que o código termine a execução dentro de DllMain?

Acredito que o problema com o código gerenciado, especificamente, é que a execução do código gerenciado pode envolver o carregamento do CLR e coisas semelhantes e não há como saber o que poderia acontecer lá que resultaria em um deadlock ... Eu não daria ouvidos ao conselho de "desabilitar este aviso "se eu fosse você, porque muito provavelmente você descobrirá que seus aplicativos travam inesperadamente em alguns cenários.


4
Estou trabalhando em um aplicativo Direct3D. Este é um EXE. No entanto, ainda estou vendo esse erro. Alguma ideia da melhor forma de consertar isso?
Agnel Kurian

18

ATUALIZAÇÃO PARA .NET 4.0 E MAIS FRAMEWORKS RECENTES

Essa é uma pergunta antiga feita na época do .Net 2.0, quando o suporte para DLLs de modo misto apresentava sérios problemas de inicialização, sujeitos a deadlocks aleatórios. A partir do .Net 4.0, a inicialização de DLLs de modo misto foi alterada. Agora, existem dois estágios separados de inicialização:

  1. Inicialização nativa, chamada no ponto de entrada da DLL, que inclui configuração nativa em tempo de execução C ++ e execução de seu método DllMain.
  2. Inicialização gerenciada, executada automaticamente pelo carregador do sistema.

Como a etapa 2 é executada fora do Loader Lock, não há deadlocks. Os detalhes são descritos em Inicialização de montagens mistas .

Para garantir que seu assembly de modo misto possa ser carregado de um executável nativo, a única coisa que você precisa verificar é se o método DllMain é declarado como código nativo. #pragma unmanagedpoderia ajudar aqui:

#pragma unmanaged

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

Também é importante que qualquer código que DllMain possa chamar direta ou indiretamente também não seja gerenciado. Faz sentido limitar o tipo de funcionalidade usada pelo DllMain para que você rastreie todo o código acessível a partir do DllMain e garanta que foi compilado com ele #pragma unmanaged.

O compilador ajuda um pouco, avisando C4747 se detectar que DllMain não foi declarado como não gerenciado:

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

No entanto, o compilador não gerará nenhum aviso se DllMain chamar indiretamente alguma outra função gerenciada, portanto, você precisa garantir que isso nunca aconteça, caso contrário, seu aplicativo pode travar aleatoriamente.


6

Pressione ctr d + e Em seguida, gaste o nó Assistentes de depuração gerenciada. Em seguida, desmarque o LoaderLock.

Espero que isso ajude você.


O atalho é alt + d + x
Narayan

3
O atalho, na verdade, depende da configuração que você especificou para usar durante a primeira execução. O layout do atalho C # é (Ctrl + D, E). (Você também pode atribuir qualquer combinação de teclas a esta função em Opções-> Ambiente-> Teclado.)
Adam LS

5

lembre os usuários do VS2017 de que você precisa desabilitar o " auxiliar de exceção " em vez do " assistente de exceção " (antes do VS2017) para evitar o erro de bloqueio do carregador, cujo caminho de configuração é Depurar-> Exceção . Corri para esse problema e perdi 2 horas procurando soluções ...


Não tenho "Exceção" em "Depurar". Tenho a comunidade VS2017 15.8.4
Alex

@Alex, verifique Debug -> Windows -> Configurações de exceção ou pressione Ctrl + Alt + E
mistika

4

Recentemente, recebi este erro ao criar uma instância de um objeto COM escrito em código nativo:

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

Isso levou ao erro descrito. Um "LoaderLock foi detectado" - exceção foi lançada.

Superei esse erro criando a instância do objeto em um thread extra:

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

myThread.Start();
myThread.Join(); // for synchronization

O erro pode acontecer com objetos Remotable (MarshalByRefObject), e esta solução não funciona para eles.
Matthieu

3

Estou construindo uma DLL C ++ CLR (MSVS2015) que precisa fazer chamadas para uma DLL não gerenciada e definir o código não gerenciado. Eu uso #pragma gerenciado e #pragma não gerenciado para controlar em que modo está para uma determinada área do código.

No meu caso, simplesmente coloquei #pragma unmanaged na frente do meu DllMain () e isso resolveu o problema. Parecia que eu queria uma versão gerenciada de DllMain ().



2

O caminho de configuração em minha instância do Visual Studio 2017 é Debug -> Windows -> Configurações de exceção. A "janela" de configurações de exceção apareceu no grupo da guia inferior (ao contrário de uma janela separada), demorei um pouco para perceber. Procure por "carregador".

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.