DLL Piekło - DLL Hell

W obliczeniowej , DLL Piekło to termin do komplikacji, które pojawiają się, gdy pracuje się z dynamicznie podłączane biblioteki (DLL) używane z Microsoft Windows systemów operacyjnych , zwłaszcza starszych 16-bitowych edycjach , które prowadzony w jednym obszarze pamięci.

DLL Hell może objawiać się na wiele różnych sposobów, w których aplikacje nie uruchamiają się ani nie działają poprawnie.

DLL Hell jest specyficzną dla systemu Windows formą ogólnej koncepcji piekła zależności .

Problemy

Biblioteki DLL są implementacją bibliotek współdzielonych firmy Microsoft . Biblioteki współdzielone umożliwiają pakowanie wspólnego kodu do opakowania, biblioteki DLL i używanie go przez dowolne oprogramowanie w systemie bez ładowania wielu kopii do pamięci. Prostym przykładem może być edytor tekstu GUI , który jest powszechnie używany przez wiele programów. Umieszczając ten kod w bibliotece DLL, wszystkie aplikacje w systemie mogą z niego korzystać bez zużywania większej ilości pamięci. Kontrastuje to z bibliotekami statycznymi , które są funkcjonalnie podobne, ale kopiują kod bezpośrednio do aplikacji. W tym przypadku każda aplikacja powiększa się o rozmiar wszystkich używanych przez nią bibliotek, co może być dość duże w przypadku nowoczesnych programów.

Problem pojawia się, gdy wersja biblioteki DLL na komputerze jest inna niż wersja, która była używana podczas tworzenia programu. Biblioteki DLL nie mają wbudowanego mechanizmu zapewniającego zgodność z poprzednimi wersjami, a nawet drobne zmiany w bibliotece DLL mogą sprawić, że jej wewnętrzna struktura będzie tak różna od poprzednich wersji, że próba ich użycia zwykle spowoduje awarię aplikacji. Biblioteki statyczne unikają tego problemu, ponieważ wersja, która została użyta do zbudowania aplikacji, jest w nich zawarta, więc nawet jeśli nowsza wersja istnieje w innym miejscu w systemie, nie ma to wpływu na aplikację.

Głównym powodem niezgodności wersji jest struktura pliku DLL. Plik zawiera katalog poszczególnych metod (procedury, procedury itp.) zawartych w bibliotece DLL oraz typy danych, które pobierają i zwracają. Nawet drobne zmiany w kodzie DLL mogą spowodować przeorganizowanie tego katalogu, w którym to przypadku aplikacja, która wywołuje określoną metodę, uważając, że jest to czwarty element w katalogu, może zakończyć się wywołaniem zupełnie innej i niezgodnej procedury, która zwykle powodują awarię aplikacji.

Istnieje kilka problemów często spotykanych z bibliotekami DLL, zwłaszcza po zainstalowaniu i odinstalowaniu wielu aplikacji w systemie. Trudności obejmują konflikty między wersjami DLL, trudności w uzyskaniu wymaganych bibliotek DLL i posiadanie wielu niepotrzebnych kopii DLL.

Rozwiązania tych problemów były znane już w czasie, gdy Microsoft pisał system DLL. Zostały one włączone do zamiennika platformy .NET „Zespoły”.

Niezgodne wersje

Określona wersja biblioteki może być kompatybilna z niektórymi programami, które jej używają, a niekompatybilna z innymi. System Windows był szczególnie podatny na to ze względu na nacisk na dynamiczne łączenie bibliotek C++ i obiektów łączenia i osadzania obiektów (OLE). Klasy C++ eksportują wiele metod, a pojedyncza zmiana w klasie, na przykład nowa metoda wirtualna, może sprawić, że będzie ona niekompatybilna z programami zbudowanymi na wcześniejszej wersji. Łączenie i osadzanie obiektów ma bardzo surowe zasady, aby temu zapobiec: interfejsy muszą być stabilne, a menedżery pamięci nie są współdzielone. Jest to jednak niewystarczające, ponieważ semantyka klasy może ulec zmianie. Poprawka błędu dla jednej aplikacji może spowodować usunięcie funkcji z innej. Przed Windows 2000 system Windows był na to podatny, ponieważ tabela klas COM była współużytkowana przez wszystkich użytkowników i procesy. Tylko jeden obiekt COM w jednym DLL/EXE może być zadeklarowany jako posiadający określony globalny identyfikator klasy COM w systemie. Jeśli jakiś program potrzebował stworzyć instancję tej klasy, otrzymywał to, co było bieżącą centralnie zarejestrowaną implementacją. W rezultacie instalacja programu, który zainstalował nową wersję wspólnego obiektu, może nieumyślnie uszkodzić inne programy, które były wcześniej zainstalowane.

Stosowanie DLL

Częsty i kłopotliwy problem występuje, gdy nowo zainstalowany program nadpisuje działającą systemową bibliotekę DLL starszą, niezgodną wersją. Wczesnymi przykładami tego były biblioteki ctl3d.dlli ctl3dv2.dlldla systemu Windows 3.1 : biblioteki stworzone przez firmę Microsoft, które wydawcy zewnętrzni rozpowszechnialiby wraz ze swoim oprogramowaniem, ale każdy z nich rozpowszechniał wersję, którą opracowali, a nie najnowszą wersję. Stosowanie DLL występuje, ponieważ:

  • Microsoft w przeszłości dystrybuował biblioteki DLL środowiska wykonawczego jako współdzielone komponenty systemu (pierwotnie C:\WINDOWS i C:\WINDOWS\SYSTEM), jako sposób na wydajne współdzielenie kodu w systemie operacyjnym ze współużytkowaną pamięcią z ograniczoną pamięcią RAM i miejscem na dysku. W związku z tym zewnętrzni programiści również rozpowszechniali je w taki sposób.
  • Instalatory aplikacji są zwykle wykonywane w uprzywilejowanym kontekście zabezpieczeń, który ma dostęp do instalowania bibliotek DLL w katalogach systemowych i edytowania rejestru systemowego w celu rejestrowania nowych bibliotek DLL jako obiektów COM . Źle napisany lub źle skonfigurowany instalator może zatem obniżyć poziom biblioteki systemowej w starszych wersjach systemu Windows, w których Ochrona plików systemu Windows lub Ochrona zasobów systemu Windows nie cofa zmiany. W systemie Windows Vista i nowszych tylko konto „zaufanego instalatora” może wprowadzać zmiany w podstawowych bibliotekach systemu operacyjnego.
  • Aplikacje Windows mogły zawierać aktualizacje systemu operacyjnego we własnych programach instalacyjnych. Oznacza to, że wiele bibliotek DLL firmy Microsoft można redystrybuować , co oznacza, że ​​aplikacje mogą je dołączyć, jeśli potrzebują usług określonych bibliotek.
  • Przed Instalatorem Windows instalatory Windows były historycznie produktami komercyjnymi; wiele osób próbowało napisać własne instalatory, przeoczając lub niewłaściwie rozwiązując problemy związane z wersjonowaniem.
  • Niektóre środowiska programistyczne nie dodały automatycznie zasobu wersji w swoich skompilowanych bibliotekach, więc wielu programistów przeoczyło ten aspekt. Sprawdzanie dat plików, nadpisywanie istniejących plików lub pomijanie operacji kopiowania, jeśli biblioteka DLL była już zainstalowana, były jedynymi dostępnymi opcjami zamiast prawidłowego wersjonowania.
  • Czasami sam system operacyjny usuwał lub zastępował biblioteki DLL starszymi lub przestarzałymi wersjami. Na przykład, Windows 2000 zainstaluje czarno-białe biblioteki DLL nad bibliotekami rozpoznającymi kolory, jeśli drukarka czarno-biała zostanie zainstalowana za drukarką kolorową.

Nieprawidłowa rejestracja COM

W modelu COM i innych częściach systemu Windows, przed wprowadzeniem zestawów obok siebie bez rejestru, rejestr był używany do określania, której podstawowej biblioteki DLL należy użyć. Jeśli zarejestrowano inną wersję modułu, ta biblioteka DLL zostanie załadowana zamiast oczekiwanej. Ten scenariusz może być spowodowany przez instalacje powodujące konflikty, które rejestrują różne wersje tych samych bibliotek, w którym to przypadku pierwszeństwo ma ostatnia instalacja.

Współdzielone moduły w pamięci

16-bitowe wersje systemu Windows (i Windows w systemie Windows ) ładują tylko jedną instancję dowolnej biblioteki DLL; wszystkie aplikacje odwołują się do tej samej kopii w pamięci, dopóki żadna aplikacja jej nie użyje i nie zostanie ona zwolniona z pamięci. (W 32-bitowych i 64-bitowych wersjach systemu Windows współużytkowanie między procesami ma miejsce tylko wtedy, gdy różne pliki wykonywalne ładują moduł z dokładnie tego samego katalogu; kod, ale nie stos, jest współużytkowany przez procesy za pośrednictwem procesu zwanego „mapowaniem pamięci”. ) Dlatego nawet jeśli żądana biblioteka DLL znajduje się w katalogu, w którym można się jej spodziewać, na przykład w katalogu systemowym lub katalogu aplikacji, żadne z tych wystąpień nie zostanie użyte, jeśli inna aplikacja została uruchomiona z niezgodną wersją z trzeci katalog. Ten problem może objawiać się 16-bitowym błędem aplikacji, który występuje tylko wtedy, gdy aplikacje są uruchamiane w określonej kolejności.

Brak serwisowalności

W bezpośrednim konflikcie z problemem ze stompingiem DLL: Jeśli aktualizacje biblioteki DLL nie wpływają na wszystkie aplikacje, które z niej korzystają, znacznie trudniej jest „obsługiwać” bibliotekę DLL – to znaczy wyeliminować problemy, które istnieją w bieżących wersjach biblioteki DLL . (Poprawki bezpieczeństwa są szczególnie atrakcyjnym i bolesnym przypadkiem). Zamiast naprawiać tylko najnowszą wersję biblioteki DLL, implementator musi w idealnym przypadku wprowadzić swoje poprawki i przetestować je pod kątem zgodności w każdej wydanej wersji biblioteki DLL.

Przyczyny

Niezgodność DLL została spowodowana przez:

  • Ograniczenia pamięci, połączone z brakiem separacji przestrzeni pamięci procesu w 16-bitowych wersjach systemu Windows;
  • Brak wymuszonych standardowych schematów wersjonowania, nazewnictwa i lokalizacji systemu plików dla bibliotek DLL;
  • Brak narzuconej standardowej metody instalacji i usuwania oprogramowania ( zarządzanie pakietami );
  • Brak scentralizowanej, autorytatywnej obsługi zarządzania i zabezpieczeń interfejsu binarnego aplikacji DLL , co pozwala na wydawanie niekompatybilnych bibliotek DLL o tej samej nazwie pliku i wewnętrznych numerach wersji;
  • Nadmiernie uproszczone narzędzia do zarządzania, uniemożliwiające identyfikację zmienionych lub problematycznych bibliotek DLL przez użytkowników i administratorów;
  • Deweloperzy przełamujący wsteczną kompatybilność funkcji we współdzielonych modułach;
  • Microsoft publikuje pozapasmowe aktualizacje składników środowiska wykonawczego systemu operacyjnego;
  • Niezdolność wcześniejszych wersji systemu Windows do uruchamiania obok siebie sprzecznych wersji tej samej biblioteki;
  • Poleganie na bieżącym katalogu lub %PATH%zmiennej środowiskowej, które zmieniają się w czasie i w zależności od systemu, w celu znalezienia zależnych bibliotek DLL (zamiast ładowania ich z jawnie skonfigurowanego katalogu);
  • Deweloperzy ponownie wykorzystują identyfikatory ClassID z przykładowych aplikacji dla interfejsów COM swoich aplikacji, zamiast generowania własnych nowych identyfikatorów GUID .

DLL Hell był bardzo powszechnym zjawiskiem w wersjach systemów operacyjnych Microsoft sprzed Windows NT, a główną przyczyną było to, że 16-bitowe systemy operacyjne nie ograniczały procesów do własnej przestrzeni pamięci, tym samym nie pozwalając im na załadowanie własnej wersji współdzielony moduł, z którym były kompatybilne. Instalatorzy aplikacji mieli być dobrymi obywatelami i weryfikować informacje o wersji DLL przed zastąpieniem istniejących systemowych bibliotek DLL. Standardowe narzędzia upraszczające wdrażanie aplikacji (co zawsze wiąże się z dostarczaniem zależnych bibliotek DLL systemu operacyjnego) zostały dostarczone przez firmę Microsoft i innych dostawców narzędzi innych firm. Firma Microsoft wymagała nawet od dostawców aplikacji, aby korzystali ze standardowego instalatora i mieli certyfikat poprawnego działania programu instalacyjnego przed uzyskaniem zgody na używanie logo Microsoft. Podejście instalatora opartego na dobrym obywatelu nie złagodziło problemu, ponieważ wzrost popularności Internetu dał więcej możliwości uzyskania niezgodnych aplikacji.

Używany przez złośliwe oprogramowanie

Niejednoznaczność, z jaką biblioteki DLL, które nie są w pełni kwalifikowane, mogą być ładowane w systemie operacyjnym Windows, została w ostatnich latach wykorzystana przez złośliwe oprogramowanie , otwierając nową klasę luk w zabezpieczeniach, które dotyczą aplikacji wielu różnych dostawców oprogramowania, a także samego systemu Windows.

Rozwiązania

Różne formy piekło DLL zostały rozwiązane lub złagodzone na przestrzeni lat.

Łączenie statyczne

Prostym rozwiązaniem biblioteki DLL Hell w aplikacji jest statyczne podpięcie wszystkich bibliotek, czyli umieszczenie w programie wymaganej wersji biblioteki, zamiast pobierania biblioteki systemowej o określonej nazwie. Jest to powszechne w aplikacjach C/C++, gdzie zamiast martwić się o to, która wersja MFC42.DLLjest zainstalowana, aplikacja jest kompilowana w celu statycznego połączenia z tymi samymi bibliotekami. To całkowicie eliminuje biblioteki DLL i jest możliwe w aplikacjach autonomicznych przy użyciu tylko bibliotek oferujących opcję statyczną, tak jak robi to Microsoft Foundation Class Library . Jednak główny cel bibliotek DLL — współdzielenie biblioteki wykonawczej między programami w celu zmniejszenia obciążenia pamięci — jest poświęcony; duplikowanie kodu biblioteki w kilku programach powoduje rozrost oprogramowania i komplikuje wdrażanie poprawek zabezpieczeń lub nowszych wersji oprogramowania zależnego.

Ochrona plików systemu Windows

Problem nadpisywania DLL (nazywany przez Microsoft DLL Stomping ) został nieco zredukowany dzięki Ochronie plików systemu Windows (WFP), wprowadzonej w systemie Windows 2000 . Zapobiega to zastępowaniu systemowych bibliotek DLL przez nieautoryzowane aplikacje, chyba że używają one określonych interfejsów API systemu Windows, które na to pozwalają. Nadal może istnieć ryzyko, że aktualizacje firmy Microsoft są niezgodne z istniejącymi aplikacjami, ale ryzyko to jest zwykle zmniejszane w bieżących wersjach systemu Windows dzięki użyciu zestawów side-by-side .

Aplikacje innych firm nie mogą podeptać plików systemu operacyjnego, chyba że dołączą legalne aktualizacje systemu Windows do swojego instalatora lub jeśli wyłączą usługę ochrony plików systemu Windows podczas instalacji, a w systemie Windows Vista lub nowszym również przejmą na własność pliki systemowe i przyznają sobie dostęp. Narzędzie SFC może w dowolnym momencie cofnąć te zmiany.

Uruchamianie sprzecznych bibliotek DLL jednocześnie

Rozwiązania tutaj polegają na posiadaniu różnych kopii tych samych bibliotek DLL dla każdej aplikacji, zarówno na dysku, jak iw pamięci.

Łatwym ręcznym rozwiązaniem konfliktów było umieszczenie różnych wersji problemowej biblioteki DLL w folderach aplikacji, a nie we wspólnym folderze systemowym. Działa to ogólnie, o ile aplikacja jest 32-bitowa lub 64-bitowa, a biblioteka DLL nie korzysta z pamięci współdzielonej. W przypadku aplikacji 16-bitowych obie aplikacje nie mogą być wykonywane jednocześnie na platformie 16-bitowej lub w tej samej 16-bitowej maszynie wirtualnej w 32-bitowym systemie operacyjnym. Technologia OLE zapobiegała temu przed systemem Windows 98 SE/2000, ponieważ wcześniejsze wersje systemu Windows miały jeden rejestr obiektów COM dla wszystkich aplikacji.

W systemie Windows 98 SE/2000 wprowadzono rozwiązanie zwane montażem side-by-side , które ładuje oddzielne kopie bibliotek DLL dla każdej aplikacji, która ich wymaga (a tym samym umożliwia jednoczesne uruchamianie aplikacji, które wymagają kolidujących bibliotek DLL). Takie podejście eliminuje konflikty, umożliwiając aplikacjom ładowanie unikalnych wersji modułu do ich przestrzeni adresowej, przy jednoczesnym zachowaniu podstawowej korzyści z udostępniania bibliotek DLL między aplikacjami (tj. zmniejszenia zużycia pamięci) dzięki użyciu technik mapowania pamięci w celu współdzielenia wspólnego kodu między różnymi procesami, które nadal użyj tego samego modułu. Jednak biblioteki DLL korzystające z danych współdzielonych między wieloma procesami nie mogą przyjąć tego podejścia. Jednym z negatywnych skutków ubocznych jest to, że osierocone wystąpienia bibliotek DLL mogą nie być aktualizowane podczas zautomatyzowanych procesów.

Aplikacje przenośne

W zależności od architektury aplikacji i środowiska wykonawczego, aplikacje przenośne mogą być skutecznym sposobem na zmniejszenie niektórych problemów z bibliotekami DLL, ponieważ każdy program zawiera własne prywatne kopie wszystkich wymaganych bibliotek DLL. Mechanizm opiera się na aplikacjach, które nie kwalifikują w pełni ścieżek do zależnych bibliotek DLL podczas ich ładowania, a system operacyjny przeszukuje katalog wykonywalny przed udostępnioną lokalizacją. Jednak technika ta może być również wykorzystywana przez złośliwe oprogramowanie, a zwiększona elastyczność może również odbywać się kosztem bezpieczeństwa, jeśli prywatne biblioteki DLL nie są aktualizowane za pomocą poprawek bezpieczeństwa w taki sam sposób, jak te współdzielone.

Wirtualizacja aplikacji może również pozwolić aplikacjom działać w „bańce”, co pozwala uniknąć instalowania plików DLL bezpośrednio w systemie operacyjnym.

Inne środki zaradcze

Istnieją inne środki zaradcze, aby uniknąć DLL Hell, z których niektóre mogą być używane jednocześnie; kilka innych funkcji, które pomagają złagodzić problem, to:

  • Narzędzia instalacyjne są teraz dołączone do Microsoft Visual Studio , jednego z głównych środowisk rozwoju systemu Windows. Narzędzia te wykonują sprawdzanie wersji przed instalacją DLL i mogą zawierać predefiniowane pakiety instalacyjne w instalacji .MSI. Umożliwia to aplikacjom innych firm integrowanie aktualizacji składników systemu operacyjnego bez konieczności pisania własnych instalatorów dla tych składników.
  • Przywracanie systemu może przywrócić system po złej instalacji, w tym po uszkodzeniu rejestru. Chociaż nie zapobiega to problemowi, ułatwia odzyskanie.
  • Katalog WinSxS ( Windows Side-by-Side ), który umożliwia współistnienie wielu wersji tych samych bibliotek.
  • Uruchamiaj 16-bitowe aplikacje w oddzielnej przestrzeni pamięci w 32-bitowej wersji systemu Windows, aby umożliwić dwóm aplikacjom jednoczesne używanie sprzecznych wersji tej samej biblioteki DLL.
  • Użyj wersji systemu Windows, która obejmuje Ochronę plików systemu Windows . Windows Me i Windows 2000 , oba wydane w 2000 roku, obsługują tę formę ochrony plików systemowych, podobnie jak Windows XP i Windows Server 2003 . Jego zamiennik, Windows Resource Protection , został wprowadzony w systemach Windows Vista i Windows Server 2008 i wykorzystuje inną metodę ochrony plików systemowych przed zmianą.
  • COM bez rejestracji: Windows XP wprowadził nowy tryb rejestracji obiektów COM o nazwie „ COM bez rejestracji ”. Ta funkcja umożliwia aplikacjom, które muszą zainstalować obiekty COM, przechowywanie wszystkich wymaganych informacji rejestru COM we własnym katalogu aplikacji, a nie w globalnym rejestrze systemowym. W ten sposób zapewnia mechanizm umożliwiający jednoczesne rejestrowanie wielu wersji tej samej biblioteki DLL przez wiele aplikacji (Microsoft nazywa to „zespołem side-by-side ”). Piekło DLL można znacznie uniknąć, używając COM bez rejestracji, jedynym ograniczeniem jest to, że wymaga on co najmniej Windows XP lub nowszych wersji Windows i że nie wolno go używać do serwerów EXE COM lub komponentów systemowych, takich jak MDAC , MSXML , DirectX lub Internet Explorer .
  • Dostarczanie systemu operacyjnego z odpowiednim systemem zarządzania pakietami, który jest w stanie śledzić zależności DLL, zachęcając do korzystania z menedżera pakietów i zniechęcając do ręcznej instalacji bibliotek DLL. Instalator Windows dołączony do systemu Windows Me , Windows 2000 i wszystkich nowszych wersji zapewnia tę funkcjonalność.
  • Posiadanie centralnej bazy danych lub uprawnień do rozwiązywania konfliktów DLL i dystrybucji oprogramowania. Zmiany w bibliotece można zgłaszać do tego organu; w ten sposób może zapewnić zachowanie zgodności w opracowanych gałęziach. Jeśli starsze oprogramowanie jest niezgodne z bieżącą biblioteką, urząd może zapewnić dla niego interfejs zgodności lub spakować starą wersję jako oddzielny pakiet.
  • Jeśli twórcy oprogramowania muszą dostosować bibliotekę i jeśli jest mało prawdopodobne, aby główne wydanie biblioteki zawierało zmiany, których potrzebują, mogą dostarczyć dostosowaną bibliotekę DLL do prywatnego użytku programu (zwykle umieszczając ją w prywatnym katalogu programu) lub połączyć statycznie program z dostosowaną biblioteką.
  • Chociaż biblioteki DLL są najlepsze do modularyzacji aplikacji i komponentów systemu oraz jako biblioteki innych firm, ich użycie nie jest konieczne we wszystkich przypadkach w nowoczesnych systemach, w których pamięć nie jest już ograniczeniem. Na przykład, jeśli aplikacja potrzebuje biblioteki, która nie będzie używana nigdzie indziej, może być połączona statycznie, bez kary miejsca i ze wzrostem prędkości.
  • Windows Vista i nowsze wersje używają specjalnej usługi TrustedInstaller do instalowania plików systemu operacyjnego. Inne konta użytkowników, w tym SYSTEM, nie mają dostępu do nadpisywania podstawowych plików binarnych systemu. Windows 7 rozszerza tę funkcjonalność na niektóre krytyczne części Rejestru.
  • Aplikacje oparte na sieci Web unikają wielu problemów związanych z pracą obok siebie, uruchamiając większość kodu na serwerze i korzystając z interfejsu przeglądarki na kliencie.

Zobacz też

Bibliografia

Linki zewnętrzne