Istnieje biblioteka DLL, która jest dynamicznie ładowana przez aplikację główną (na komputerze) poprzez Windows.LoadLibrary
. Dzieje się tak dlatego, że istnieje wiele podobnych bibliotek DLL i tylko kilka do pojedynczego z nich wymaga załadowania w środowisku wykonawczym. Więc łączenie statyczne nie jest opcją.Czy biblioteki DLL Delphi są predefiniowane pod kątem blokad ładujących?
Problem polega na tym, że co pewien czas zawiesza się główna aplikacja podczas ładowania jednej z tych bibliotek DLL. Zauważ, że problem może się zdarzyć w przypadku każdego z nich. Prawdopodobnie dlatego, że mają wiele wspólnego kodu.
Problemem wydaje się być blokada ładowarki (see this SO answer on what it is). Znalazłem kawałek wspólnego kodu, który jest używany przez wszystkie biblioteki DLL przy uruchamianiu w jednostce begin...end
- jednostki library
(to jest project.dpr
), gdzie używane są GetModuleHandle
i GetProcAddress
.
I okazało się, że jest to zupełnie NIE z bibliotek DLL, jak begin...end
-section pliku projektu DLL jest w rzeczywistości DllMain
funkcja biblioteki i wywołanie tych funkcji może prowadzić do martwych zamki (nazwane ładowarka blokada) . Przeczytałem to w tym Microsoft Best Practice Guide.
Więc odbudowałem swój kod, że te połączenia są wywoływane później, gdy połączenie Windows.LoadLibrary
zostało zakończone.
Niestety, problem z wiszącym pozostaje. :-(
Uruchomiłem debuggera, przechodząc przez każdą inicjalizację, która jest wywoływana, nawet przed wykonaniem pojedynczej linii mojego kodu. Stwierdziłem, że wiele kodu strony trzeciej jest sprzeczne z instrukcją co zrobić i czego nie robić w kodzie inicjującym DLL:
- TMS Komponent Pakiet
- JEDI Biblioteka komponentów
- OmniThreadLibrary
- Indy Komponenty
Wszystkie powyższe dynamicznie ładują inne biblioteki DLL w kodzie initialization
lub wysyłają zapytania do procedur za pośrednictwem GetProcAddress
. Myślę, że te wywołania powodują zawieszanie się podczas ładowania bibliotek DLL.
Czy tylko nieliczni programiści Delphi wiedzą o niebezpieczeństwach związanych z initialization
? Co mogę z tym zrobić?
'GetModuleHandle()' i 'GetProcAddress()' są bezpieczne w użyciu podczas inicjowania biblioteki DLL, w dokumencie, z którym się łączyłeś. Indy dynamicznie ładuje kilka bibliotek DLL w środowisku wykonawczym, ale żadna z nich nie powinna była zostać wczytana w żadnych sekcjach "inicjalizujących", są one ładowane dynamicznie w razie potrzeby podczas wywoływania funkcji DLL. Ale właśnie znalazłem 1 DLL (zlib), który jest ładowany w sekcji 'inicjalizacji', więc naprawiłem to teraz. –
Zobacz sekcję "biblioteka" w dokumentacji funkcji API. GetModuleHandle i GetProcAddress są funkcjami jądra. –
Więc ta strona internetowa (https://blog.barthe.ph/2009/07/30/no-stdlib-in-dllmai/) jest błędna w odniesieniu do 'GetModuleHandle'? Jest napisane: "Ta" blokada programu ładującego "jest pobierana za każdym razem, gdy biblioteka jest ładowana, ale także wtedy, gdy używane są funkcje takie jak GetModuleHandle() lub GetModuleFileName()." * –