В вычислениях Ад DLL - это термин, обозначающий осложнения, возникающие при работает с библиотеками динамической компоновки (DLL), используемыми с Microsoft Windows операционными системами, особенно с устаревшими 16-битными версиями, которые все запускаются в едином пространстве памяти.
DLL Hell может проявляться по-разному, когда приложения не запускаются и не работают правильно.
DLL Hell - это специфическая для экосистемы Windows форма общей концепции ад зависимостей.
DLL - это реализация Microsoft общие библиотеки. Общие библиотеки позволяют объединить общий код в оболочку, DLL, и использовать его любым прикладным программным обеспечением в системе без загрузки нескольких копий в память. Простым примером может служить текстовый редактор GUI, который широко используется во многих программах. Поместив этот код в DLL, все приложения в системе смогут использовать его без использования дополнительной памяти. Это контрастирует со статическими библиотеками , которые функционально похожи, но копируют код непосредственно в приложение. В этом случае каждое приложение увеличивается на размер всех используемых им библиотек, а для современных программ он может быть довольно большим.
Проблема возникает, когда версия библиотеки DLL на компьютере отличается от версии, которая использовалась при создании программы. Библиотеки DLL не имеют встроенного механизма обратной совместимости, и даже незначительные изменения в DLL делают ее внутреннюю структуру настолько отличной от предыдущих версий, что попытка их использования обычно вызывает сбой приложения. Статические библиотеки позволяют избежать этой проблемы, поскольку версия, которая использовалась для сборки приложения, включена в нее, поэтому даже если в другом месте системы существует более новая версия, это не влияет на приложение.
Основной причиной несовместимости версий является структура файла DLL. Файл содержит каталог отдельных методов (процедур, подпрограмм и т. Д.), Содержащихся в DLL, и типов данных, которые они принимают и возвращают. Даже незначительные изменения в коде DLL могут привести к переупорядочению этого каталога, и в этом случае приложение, которое вызывает определенный метод, полагая, что это 4-й элемент в каталоге, может в конечном итоге вызвать совершенно другую и несовместимую процедуру, которая будет обычно вызывает сбой приложения.
Существует несколько проблем, с которыми обычно сталкиваются библиотеки DLL, особенно после того, как в системе были установлены и удалены многочисленные приложения. Сложности включают конфликты между версиями DLL, трудности с получением необходимых DLL и наличие множества ненужных копий DLL.
Решения этих проблем были известны еще тогда, когда Microsoft писала систему DLL. Они были включены в замену .NET, "Сборки".
Определенная версия библиотеки может быть совместима с некоторыми программами, которые ее используют, и несовместима с другими. Windows была особенно уязвима для этого из-за ее упора на динамическое связывание библиотек C ++ и объектов связывание и внедрение объектов (OLE). Классы C ++ экспортируют множество методов, и одно изменение класса, например новый виртуальный метод, может сделать его несовместимым с программами, созданными для более ранней версии. Для предотвращения этого существуют очень строгие правила связывания и внедрения объектов: интерфейсы должны быть стабильными, а диспетчеры памяти не используются совместно. Однако этого недостаточно, поскольку семантика класса может измениться. Исправление ошибки в одном приложении может привести к удалению функции из другого. До Windows 2000 Windows была уязвима для этого, потому что таблица классов COM была совместно использована всеми пользователями и процессами. Только один COM-объект в одной DLL / EXE может быть объявлен как имеющий конкретный глобальный идентификатор COM-класса в системе. Если какой-либо программе требовалось создать экземпляр этого класса, она получала то, что было текущей централизованно зарегистрированной реализацией. В результате установка программы, устанавливающей новую версию общего объекта, может случайно нарушить работу других программ, которые были установлены ранее.
Распространенная и неприятная проблема возникает, когда недавно установленная программа перезаписывает рабочую системную DLL более ранней несовместимой версией. Ранними примерами этого были библиотеки ctl3d.dll
и ctl3dv2.dll
для Windows 3.1 : библиотеки, созданные Microsoft, которые сторонние издатели будут распространять вместе со своим программным обеспечением., но каждый распространяет версию, с которой они разработали, а не самую последнюю версию. Вытеснение DLL происходит из-за того, что:
В COM и другие части Windows, до появления параллельных сборок без реестра, Реестр использовался для определения того, какую базовую DLL следует использовать. Если была зарегистрирована другая версия модуля, эта DLL загружалась бы вместо ожидаемой. Этот сценарий может быть вызван конфликтующими установками, в которых регистрируются разные версии одних и тех же библиотек, и в этом случае последняя установка будет иметь приоритет.
16-битные версии Windows (и Windows в Windows ) загружают только один экземпляр любой данной DLL; все приложения ссылаются на одну и ту же копию в памяти, пока никакие приложения не используют ее, и она не выгружается из памяти. (Для 32-разрядных и 64-разрядных версий Windows совместное использование между процессами происходит только тогда, когда разные исполняемые файлы загружают модуль из одного и того же каталога; код, но не стек , совместно используется процессами через процесс называется «сопоставлением памяти».) Таким образом, даже если желаемая DLL находится в каталоге, где можно ожидать, что она будет найдена, например, в системном каталоге или каталоге приложения, ни один из этих экземпляров не будет использоваться, если другое приложение запустил несовместимую версию из третьего каталога. Эта проблема может проявляться как ошибка 16-разрядного приложения, которая возникает только при запуске приложений в определенном порядке.
В прямом конфликте с проблемой выталкивания DLL: если обновления библиотеки DLL не влияют на все приложения, которые ее используют, тогда становится намного сложнее "обслуживать" DLL - то есть для устранения проблем, существующих в текущих версиях библиотеки DLL. (Исправления безопасности - особенно убедительный и болезненный случай.) Вместо исправления только последней версии DLL разработчик в идеале должен внести свои исправления и протестировать их на совместимость с каждой выпущенной версией DLL.
Несовместимость DLL была вызвана:
% PATH%
, которые меняются со временем и от системы к системе, для поиска зависимых библиотек DLL (вместо того, чтобы загружать их из явного сконфигурированный каталог);DLL Hell было очень распространенным явлением на до- Версии Windows NT операционных систем Microsoft, основная причина в том, что 16-разрядные операционные системы не ограничивали процессы своим собственным пространством памяти, тем самым не позволяя им загружать свою собственную версию разделяемого модуля, с которым они были совместимы. Ожидалось, что установщики приложений будут добрыми гражданами и проверят информацию о версии DLL перед перезаписью существующих системных DLL. Стандартные инструменты для упрощения развертывания приложений (которые всегда включают доставку зависимых библиотек DLL операционной системы) были предоставлены Microsoft и другими сторонними поставщиками инструментов. Microsoft даже потребовала от поставщиков приложений использовать стандартный установщик и сертифицировать свою программу установки для правильной работы, прежде чем им будет разрешено использовать логотип Microsoft. Подход «добросовестного установщика» не смягчил проблему, поскольку рост популярности Интернета предоставил больше возможностей для получения несовместимых приложений.
Неопределенность, с которой не полностью квалифицированные библиотеки DLL могут быть загружены в операционную систему Windows, в последние годы использовалась вредоносным ПО, открывая новый класс уязвимостей, который затрагивает приложения от многих различных поставщиков программного обеспечения, а также саму Windows.
За прошедшие годы были устранены или смягчены различные формы ада DLL.
Простое решение проблемы DLL Hell в приложении - это статически связать все библиотеки, т.е. включить версию библиотеки, требуемую в программу, вместо подбирая системную библиотеку с указанным именем. Это обычное явление в приложениях C / C ++, где вместо того, чтобы беспокоиться о том, какая версия MFC42.DLL
установлена, приложение компилируется для статической компоновки с теми же библиотеками. Это полностью исключает библиотеки DLL и возможно в автономных приложениях, использующих только библиотеки, которые предлагают статический вариант, как это делает Microsoft Foundation Class Library. Однако основная цель DLL - совместное использование библиотек времени выполнения между программами для уменьшения накладных расходов памяти - принесена в жертву; дублирование кода библиотеки в нескольких программах создает раздувание программного обеспечения и усложняет развертывание исправлений безопасности или более новых версий зависимого программного обеспечения.
Проблема перезаписи DLL (называемая Microsoft «выталкиванием DLL») была несколько уменьшена с помощью Windows File Protection (WFP), которая была представлена в Windows 2000. Это предотвращает перезапись системных DLL неавторизованными приложениями, если только они не используют специальные Windows API, которые это разрешают. По-прежнему может существовать риск того, что обновления от Microsoft несовместимы с существующими приложениями, но этот риск обычно снижается в текущих версиях Windows за счет использования параллельных сборок.
Сторонние приложения не могут вытеснить Файлы ОС, если они не связывают законные обновления Windows со своим установщиком, или если они не отключают службу Windows File Protection во время установки, а в Windows Vista или более поздних версиях также берут на себя ответственность за системные файлы и предоставляют себе доступ. Утилита SFC может отменить эти изменения в любое время.
Решения здесь заключаются в наличии разных копий одних и тех же DLL для каждого приложения как на диске, так и в памяти.
Простым ручным решением конфликтов было размещение различных версий проблемной DLL в папках приложений, а не в общей общесистемной папке. В целом это работает, если приложение является 32-разрядным или 64-разрядным и DLL не использует разделяемую память. В случае 16-разрядных приложений два приложения не могут выполняться одновременно на 16-разрядной платформе или на одной и той же 16-разрядной виртуальной машине в 32-разрядной операционной системе. OLE предотвращал это до Windows 98 SE / 2000, потому что более ранние версии Windows имели единый реестр COM-объектов для всех приложений.
Windows 98 SE / 2000 представила решение под названием параллельная сборка, которое загружает отдельные копии библиотек DLL для каждого приложения, которому они необходимы (и, таким образом, позволяет приложениям, требующим конфликтующие библиотеки DLL, работать одновременно). Этот подход устраняет конфликты, позволяя приложениям загружать уникальные версии модуля в свое адресное пространство, сохраняя при этом основное преимущество совместного использования библиотек DLL между приложениями (т. Е. Сокращение использования памяти) за счет использования методов сопоставления памяти для совместного использования общего кода между различными процессами, которые все еще работают. используйте тот же модуль. Однако библиотеки DLL, использующие общие данные между несколькими процессами, не могут использовать этот подход. Одним из отрицательных побочных эффектов является то, что потерянные экземпляры DLL могут не обновляться во время автоматизированных процессов.
В зависимости от архитектуры приложения и среды выполнения переносимые приложения могут быть эффективным способом уменьшить некоторые проблемы с DLL, поскольку каждая программа связывает свои собственные частные копии любых необходимых DLL. Механизм основан на том, что приложения не полностью определяют пути к зависимым библиотекам DLL при их загрузке, а операционная система выполняет поиск в каталоге исполняемых файлов до любого общего расположения. Однако этот метод также может быть использован вредоносными программами, и повышенная гибкость также может быть достигнута за счет безопасности, если частные библиотеки DLL не обновляются с помощью исправлений безопасности так же, как и общие.
Виртуализация приложений также может позволить приложениям работать в «пузыре», что позволяет избежать установки файлов DLL непосредственно в операционную систему.
Существуют и другие контрмеры, чтобы избежать DLL Hell, некоторые из которых, возможно, придется использовать одновременно; некоторые другие функции, которые помогают смягчить проблему: