Błąd blokady programu ładującego


95

Buduję na C ++ dll, pisząc kod w C #.

Otrzymuję błąd, mówiąc

Wykryto LoaderLock Komunikat: Próba zarządzanego wykonania wewnątrz blokady modułu ładującego systemu operacyjnego. Nie próbuj uruchamiać kodu zarządzanego wewnątrz funkcji DllMain lub inicjalizacji obrazu, ponieważ może to spowodować zawieszenie aplikacji.

Próbowałem sprawdzić, co dokładnie oznacza ten błąd, ale rysuję bezsensowne artykuły, głównie mówiąc, że to tylko ostrzeżenie i powinienem to wyłączyć w Visual Studio. Inne rozwiązania wydają się być spowodowane przez iTunes lub ten problem występujący podczas programowania z DirectX. Mój problem nie jest związany z żadnym.

Czy ktoś może wyjaśnić, co to właściwie oznacza?


Czuję z tobą, mam ten sam problem i co mnie najbardziej zaskakuje: moja dll nie jest nawet kodem zarządzanym, więc dlaczego / jak ma używać zarządzanego kodu na (nieistniejącym) DllMain?
Sam

Otrzymałem to ostrzeżenie podczas próby wyświetlenia zawartości zestawu danych w trybie debugowania. Używam C #, stało się to w zwykłej formie systemu Windows.
Soenhay

Ponieważ nie możesz znaleźć przyczyny (jak skomentowałeś w górnej odpowiedzi), podejrzewam, że ładujesz plik DLL, który popełnia przestępstwo.
John Thoits

Odpowiedzi:


70

musisz przejść do menu Debug -> Wyjątki, otworzyć Managed Debugging Assistants, znaleźć LoaderLock i odznaczyć

http://goo.gl/TGAHV


21
tak, to jest sposób na wyłączenie ostrzeżenia; Ale nawet po 2 latach nie zorientowałem się dokładnie, dlaczego tak się dzieje.
Devdatta Tengshe

2
Zdarzyło mi się to, gdy otworzyłem stary projekt w VS 2012
4imble

1
Jestem z tobą @Kohan. Otworzyłem też starszy projekt i wyskoczył mi błąd. Wyłączyłem wyjątek, ale chciałbym dowiedzieć się, co można zrobić, aby temu zapobiec.
Pimenta,

1
Jeśli uruchomię projekt jako debugowanie natywne, z domyślnymi wszystkimi wyjątkami (resetuj wszystko), w oknie debugowania pojawi się <mda: msg xmlns: mda = " schemas.microsoft.com/CLR/2004/10/mda "> <! - - Próba zarządzanego wykonania w blokadzie programu ładującego system operacyjny .... etc -> <mda: loaderLockMsg break = "true" /> </ mda: msg> VS następnie przedstawia wiele punktów przerwania podczas sekwencji CTOR. Wyłączenie ustawienia LoaderLock nie pomaga. Dla mnie musiałem zaznaczyć górną opcję MDA (dla WSZYSTKICH MDA), a następnie odznaczyć opcję najwyższego poziomu (dla braku MDA), a następnie zbudować + uruchomić. To nie zadziałało dla mojego kolegi.
GilesDMiddleton

17
Chciałem udostępnić aktualizację w VS2015, teraz musisz przejść do Debug->Windows->Exception Settings. Reszta jest taka sama zManaged Debugging Assistants \ LoaderLock
jxramos

52

Ogólna idea blokady modułu ładującego: System uruchamia kod w DllMain wewnątrz zamka (jak blokada synchronizacji). Dlatego uruchamianie nietrywialnego kodu wewnątrz DllMain jest „pytaniem o zakleszczenie”, jak opisano tutaj .

Pytanie brzmi, dlaczego próbujesz uruchomić kod wewnątrz DllMain? Czy ważne jest, aby ten kod działał w kontekście DllMain, czy też można stworzyć nowy wątek i uruchomić w nim kod, a nie czekać, aż kod zakończy wykonywanie w DllMain?

Uważam, że problem w szczególności z kodem zarządzanym polega na tym, że uruchomienie kodu zarządzanego może wiązać się z ładowaniem CLR i tym podobnych i nie wiadomo, co mogłoby się tam zdarzyć, co spowodowałoby zakleszczenie ... Nie zważałbym na radę „wyłącz to ostrzeżenie „Na twoim miejscu, ponieważ jest największe prawdopodobieństwo, że w niektórych sytuacjach Twoje aplikacje będą się zawieszać.


4
Pracuję nad aplikacją Direct3D. To jest plik EXE. Jednak nadal widzę ten błąd. Jakieś pomysły, jak najlepiej to naprawić?
Agnel Kurian,

18

AKTUALIZACJA DLA .NET 4.0 I NOWOCZESNYCH RAM

Jest to stare pytanie zadawane w czasie .Net 2.0, kiedy obsługa bibliotek DLL trybu mieszanego miała poważne problemy z inicjalizacją, podatne na losowe zakleszczenia. Począwszy od .Net 4.0, zmieniła się inicjalizacja bibliotek DLL trybu mieszanego. Teraz są dwa oddzielne etapy inicjalizacji:

  1. Natywna inicjalizacja wywoływana w punkcie wejścia biblioteki DLL, która obejmuje natywną konfigurację środowiska wykonawczego C ++ i wykonanie metody DllMain.
  2. Zarządzana inicjalizacja, wykonywana automatycznie przez program ładujący system.

Ponieważ krok # 2 jest wykonywany poza blokadą modułu ładującego, nie ma zakleszczeń. Szczegóły opisano w sekcji Inicjalizacja zestawów mieszanych .

Aby upewnić się, że zestaw trybu mieszanego można załadować z natywnego pliku wykonywalnego, jedyną rzeczą, którą musisz sprawdzić, jest to, że metoda DllMain jest zadeklarowana jako kod natywny. #pragma unmanagedmoże pomóc tutaj:

#pragma unmanaged

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

Ważne jest również, aby każdy kod, który DllMain może wywołać bezpośrednio lub pośrednio, był również niezarządzany. Sensowne jest ograniczenie typu funkcji używanej przez DllMain, aby śledzić cały kod osiągalny z DllMain i upewnić się, że jest on skompilowany #pragma unmanaged.

Kompilator trochę pomaga, ostrzegając C4747, jeśli wykryje, że DllMain nie jest zadeklarowany jako niezarządzany:

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

Jednak kompilator nie wygeneruje żadnych ostrzeżeń, jeśli DllMain pośrednio wywoła inną funkcję zarządzaną, więc musisz upewnić się, że nigdy się to nie zdarzy, w przeciwnym razie aplikacja może się losowo zablokować.


6

Naciśnij ctr d + e, a następnie rozwiń węzeł asystentów zarządzanego debugowania. Następnie odznacz LoaderLock.

Mam nadzieję, że to ci pomoże.


Skrót to alt + d + x
Narayan

3
Skrót w rzeczywistości zależy od konfiguracji określonej do użycia podczas pierwszego uruchomienia. Układ skrótów C # to (Ctrl + D, E). (Możesz również przypisać dowolną kombinację klawiszy do tej funkcji w Opcje-> Środowisko-> Klawiatura.)
Adam LS,

6

uprzejmie przypomnij tym użytkownikom VS2017 , że należy wyłączyć „ pomocnika wyjątków ” zamiast „ asystenta wyjątków ” (przed VS2017), aby zapobiec wystąpieniu błędu blokady modułu ładującego, którego ścieżka ustawień to Debug-> Wyjątek . Właśnie wpadłem na ten problem i zmarnowałem 2 godziny na szukanie rozwiązań ...


Nie mam „Wyjątku” w „Debuguj”. Mam społeczność VS2017 15.8.4
Alex

@Alex, sprawdź debugowanie -> Windows -> Ustawienia wyjątków lub naciśnij Ctrl + Alt + E
mistika

4

Niedawno wystąpił ten błąd podczas tworzenia wystąpienia obiektu COM napisanego w kodzie natywnym:

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

Doprowadziło to do opisanego błędu. Zgłoszono wyjątek „LoaderLock został wykryty”.

Pokonałem ten błąd, tworząc instancję obiektu w dodatkowym wątku:

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

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

Błąd może wystąpić w przypadku obiektów zdalnych (MarshalByRefObject), a to rozwiązanie nie działa dla nich.
Matthieu

3

Buduję bibliotekę DLL CLR C ++ (MSVS2015), która ma wykonywać wywołania do niezarządzanej biblioteki DLL i definiować niezarządzany kod. Używam #pragma managed i #pragma unmanaged, aby kontrolować, w jakim trybie jest dla danego obszaru kodu.

W moim przypadku po prostu wstawiłem #pragma unmanaged przed moją DllMain () i to rozwiązało problem. Wydawało się, że chciałem mieć zarządzaną wersję DllMain ().



2

Ścieżka ustawień w moim wystąpieniu programu Visual Studio 2017 to Debug -> Windows -> Ustawienia wyjątków. „Okno” ustawień wyjątku, które pojawiło się w dolnej grupie zakładek (w przeciwieństwie do osobnego okna), zajęło mi trochę czasu, zanim to zauważyłem. Wyszukaj „loader”.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.