В вычислении , DLL ад термин для осложнений , которые возникают , когда один работает с динамически подключаемых библиотек (DLL) , используемых с Microsoft Windows операционных систем , [1] в частности , устаревшие 16-разрядные версии , которые все работают в одном пространстве памяти.
DLL Hell может проявляться по-разному, при этом приложения не запускаются и не работают правильно.
DLL Hell - это специфическая для экосистемы Windows форма общей концепции ада зависимостей .
Проблемы
DLL - это реализация разделяемых библиотек Microsoft . Общие библиотеки позволяют объединить общий код в оболочку, DLL, и использовать его любым прикладным программным обеспечением в системе без загрузки нескольких копий в память. Простым примером может служить текстовый редактор графического интерфейса пользователя , который широко используется во многих программах. Поместив этот код в 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 топает
Распространенная и неприятная проблема возникает, когда недавно установленная программа перезаписывает рабочую системную DLL более ранней несовместимой версией. Ранние примеры этого были ctl3d.dll
и ctl3dv2.dll
библиотеки для Windows 3.1 : Microsoft-созданные библиотеки, сторонние издатели распространять с их программным обеспечением, но каждый раздаточный версию они разработали с , а не самой последней версии. [2] Вытеснение DLL происходит по следующим причинам:
- В прошлом Microsoft распределяла динамические библиотеки DLL в качестве общих системных компонентов [3] (первоначально C: \ WINDOWS и C: \ WINDOWS \ SYSTEM) как способ эффективного совместного использования кода в ОС с общей памятью с ограниченным ОЗУ и дисковым пространством. Следовательно, сторонние разработчики также распространяли их таким образом.
- Установщики приложений обычно выполняются в привилегированном контексте безопасности, который имеет доступ для установки библиотек DLL в системные каталоги и для редактирования системного реестра для регистрации новых библиотек DLL как объектов COM . Поэтому плохо написанный или неправильно настроенный установщик может понизить версию системной библиотеки в устаревших версиях Windows, в которых защита файлов Windows или защита ресурсов Windows не откатывают изменение. В Windows Vista и более поздних версиях только учетная запись «доверенного установщика» может вносить изменения в основные библиотеки операционной системы.
- Приложениям Windows было разрешено включать обновления ОС в свои собственные программы установки. То есть многие библиотеки DLL Microsoft являются распространяемыми , что означает, что приложения могут включать их, если им нужны службы конкретных библиотек.
- До установщика Windows установщики Windows исторически были коммерческими продуктами; многие люди пытались написать свои собственные установщики, не обращая внимания на проблемы с версией или неправильно решая их в процессе. [ необходима цитата ]
- Некоторые среды разработки не добавляли автоматически ресурс версии в свои скомпилированные библиотеки, поэтому многие разработчики упустили этот аспект. Проверка дат файлов, перезапись существующих файлов или пропуск операции копирования, если DLL уже была установлена, были единственными доступными вариантами вместо правильного управления версиями. [ необходима цитата ]
- Иногда сама ОС удаляла или заменяла библиотеки DLL более старыми или устаревшими версиями. Например, Windows 2000 установит библиотеки DLL черно-белого принтера поверх DLL с поддержкой цвета, если после цветного принтера был установлен черно-белый принтер. [4]
Неправильная регистрация COM
В COM - и другие части ОС Windows, до введения бока о боке реестра свободных сборок, [5] реестр был использован для определения того, какие библиотеки DLL , лежащее в основе употребление. Если была зарегистрирована другая версия модуля, эта DLL будет загружена вместо ожидаемой. Этот сценарий может быть вызван конфликтующими установками, в которых регистрируются разные версии одних и тех же библиотек, и в этом случае будет преобладать последняя установка.
16-разрядные версии Windows (и Windows в Windows ) загружают только один экземпляр любой данной DLL; все приложения ссылаются на одну и ту же копию в памяти, пока никакие приложения не будут ее использовать, и она не будет выгружена из памяти. (Для 32-разрядных и 64-разрядных версий Windows совместное использование между процессами происходит только тогда, когда разные исполняемые файлы загружают модуль из одного и того же каталога; код, но не стек , совместно используется процессами через процесс, называемый «отображение памяти». Таким образом, даже если желаемая DLL находится в каталоге, где можно ожидать, что она будет найдена, например, в системном каталоге или каталоге приложения, ни один из этих экземпляров не будет использоваться, если другое приложение было запущено с несовместимой версией из третий каталог. Эта проблема может проявляться как ошибка 16-разрядного приложения, которая возникает только при запуске приложений в определенном порядке.
Отсутствие работоспособности
В прямом конфликте с проблемой выталкивания DLL: если обновления библиотеки DLL не влияют на все приложения, которые ее используют, то становится намного сложнее "обслуживать" DLL, то есть устранять проблемы, существующие в текущих версиях DLL. . (Исправления безопасности - особенно убедительный и болезненный случай.) Вместо исправления только последней версии DLL разработчик в идеале должен внести свои исправления и протестировать их на совместимость с каждой выпущенной версией DLL.
Причины
Несовместимость DLL была вызвана:
- Ограничения памяти в сочетании с отсутствием разделения пространства памяти процесса в 16-битных версиях Windows;
- Отсутствие принудительных стандартных схем управления версиями, именами и расположением файловой системы для библиотек DLL;
- Отсутствие принудительного стандартного метода установки и удаления программного обеспечения ( управление пакетами );
- Отсутствие централизованной авторитетной поддержки управления двоичным интерфейсом приложения DLL и средств защиты, что позволяет выпускать несовместимые библиотеки DLL с тем же именем файла и внутренними номерами версий;
- Упрощенные инструменты управления, предотвращающие идентификацию измененных или проблемных DLL пользователями и администраторами;
- Разработчики нарушают обратную совместимость функций в разделяемых модулях;
- Microsoft выпускает внеполосные обновления для компонентов среды выполнения операционной системы;
- Неспособность более ранних версий Windows запускать параллельно конфликтующие версии одной и той же библиотеки;
- Использование текущего каталога или
%PATH%
переменной среды, которые меняются со временем и от системы к системе, для поиска зависимых библиотек DLL (вместо загрузки их из явно настроенного каталога); - Разработчики повторно используют идентификаторы ClassID из примеров приложений для COM-интерфейсов своих приложений, вместо того, чтобы создавать свои собственные новые идентификаторы GUID .
DLL Hell был очень распространенным явлением в версиях операционных систем Microsoft до Windows NT, основная причина заключалась в том, что 16-разрядные операционные системы не ограничивали процессы своим собственным пространством памяти, тем самым не позволяя им загружать свою собственную версию общий модуль, с которым они были совместимы. Ожидалось, что установщики приложений будут хорошими гражданами и проверят информацию о версии DLL перед перезаписью существующих системных DLL. Стандартные инструменты для упрощения развертывания приложений (которые всегда включают доставку зависимых библиотек DLL операционной системы) были предоставлены Microsoft и другими сторонними поставщиками инструментов. Microsoft даже потребовала, чтобы поставщики приложений использовали стандартный установщик и чтобы их программа установки была сертифицирована для правильной работы, прежде чем им будет разрешено использовать логотип Microsoft. Подход «добросовестного установщика» не смягчил проблему, поскольку рост популярности Интернета предоставил больше возможностей для получения несовместимых приложений.
Использование вредоносным ПО
Неопределенность, с которой не полностью квалифицированные библиотеки DLL могут быть загружены в операционную систему Windows, в последние годы использовалась вредоносными программами [ когда? ] , открывая новый класс уязвимостей, который затрагивает приложения от многих различных поставщиков программного обеспечения, а также саму Windows. [6]
Решения
Различные формы DLL-ада были решены или смягчены на протяжении многих лет.
Статическое связывание
Простое решение проблемы DLL Hell в приложении - статически связать все библиотеки, то есть включить версию библиотеки, требуемую в программу, вместо того, чтобы выбирать системную библиотеку с указанным именем. [7] Это распространено в приложениях C / C ++, где вместо того, чтобы беспокоиться о том, какая версия MFC42.DLL
установлена, приложение компилируется для статической компоновки с теми же библиотеками. Это полностью исключает библиотеки DLL и возможно в автономных приложениях, использующих только библиотеки, которые предлагают статический вариант, как это делает библиотека Microsoft Foundation Class . Однако основная цель DLL - совместное использование библиотек времени выполнения между программами для уменьшения накладных расходов памяти - принесена в жертву; дублирование кода библиотеки в нескольких программах приводит к раздуванию программного обеспечения и усложняет развертывание исправлений безопасности или новых версий зависимого программного обеспечения.
Защита файлов Windows
Проблема перезаписи DLL (упоминаемая Microsoft как DLL Stomping ) была несколько уменьшена с помощью Windows File Protection (WFP) [8], появившейся в Windows 2000 . [9] Это предотвращает перезапись системных библиотек DLL неавторизованными приложениями, если они не используют определенные API Windows, которые это разрешают. По-прежнему может существовать риск того, что обновления от Microsoft несовместимы с существующими приложениями, но этот риск обычно снижается в текущих версиях Windows за счет использования параллельных сборок .
Сторонние приложения не могут обрабатывать файлы ОС, если они не связывают законные обновления Windows со своим установщиком или если они не отключают службу защиты файлов Windows во время установки, а в Windows Vista или более поздних версиях также приобретают права собственности на системные файлы и предоставляют себе доступ. SFC утилита может восстановить эти изменения в любое время.
Одновременный запуск конфликтующих DLL
Решения здесь состоят в наличии разных копий одних и тех же библиотек DLL для каждого приложения как на диске, так и в памяти.
Простым ручным решением конфликтов было размещение различных версий проблемной DLL в папках приложений, а не в общей общесистемной папке. В целом это работает, если приложение является 32-разрядным или 64-разрядным и DLL не использует разделяемую память. В случае 16-битных приложений два приложения не могут выполняться одновременно на 16-битной платформе или на одной и той же 16-битной виртуальной машине в 32-битной операционной системе. OLE предотвращало это до Windows 98 SE / 2000, потому что более ранние версии Windows имели единый реестр COM-объектов для всех приложений.
Windows 98 SE / 2000 представил решение под названием бок о боке сборки , [10] , который загружает отдельные копии библиотек DLL для каждого приложения , которое требует от них (и , таким образом , позволяет приложения , которые требуют конфликтующих библиотек DLL для запуска одновременно). Этот подход устраняет конфликты, позволяя приложениям загружать уникальные версии модуля в свое адресное пространство, сохраняя при этом основное преимущество совместного использования библиотек DLL между приложениями (т. Е. Сокращение использования памяти) за счет использования методов сопоставления памяти для совместного использования общего кода между различными процессами, которые все еще работают. используйте тот же модуль. Однако библиотеки DLL, использующие общие данные между несколькими процессами, не могут использовать этот подход. [11] Одним из отрицательных побочных эффектов является то, что потерянные экземпляры DLL могут не обновляться во время автоматизированных процессов.
Портативные приложения
В зависимости от архитектуры приложения и среды выполнения переносимые приложения могут быть эффективным способом уменьшить некоторые проблемы с DLL, поскольку каждая программа связывает свои собственные частные копии любых требуемых DLL. [9] Механизм основан на том, что приложения не полностью определяют пути к зависимым библиотекам DLL при их загрузке, а операционная система выполняет поиск в каталоге исполняемых файлов перед любым совместно используемым местоположением. [12] Однако этот метод также может быть использован вредоносными программами, [13] и повышенная гибкость также может быть достигнута за счет безопасности, если частные библиотеки DLL не обновляются с помощью исправлений безопасности таким же образом, как и общие. .
Виртуализация приложений также может позволить приложениям работать в «пузыре», что позволяет избежать установки файлов DLL непосредственно в операционную систему.
Другие меры противодействия
Есть и другие меры противодействия DLL Hell, некоторые из которых, возможно, придется использовать одновременно; некоторые другие функции, которые помогают смягчить проблему:
- Инструменты установки теперь включены в Microsoft Visual Studio , одну из основных сред разработки Windows. Эти инструменты выполняют проверку версии перед установкой DLL и могут включать предопределенные установочные пакеты в установку .MSI. Это позволяет сторонним приложениям интегрировать обновления компонентов ОС без необходимости писать собственные установщики для этих компонентов.
- Восстановление системы может восстановить систему после неправильной установки, включая повреждение реестра. Хотя это не предотвращает проблему, но облегчает ее устранение.
- Каталог WinSxS ( Windows Side-by-Side ), который позволяет сосуществовать нескольким версиям одних и тех же библиотек.
- Запускайте 16-разрядные приложения в отдельном пространстве памяти в 32-разрядной версии Windows, чтобы два приложения могли одновременно использовать конфликтующие версии одной и той же библиотеки DLL.
- Используйте версию Windows, которая включает защиту файлов Windows . Windows Me и Windows 2000 , выпущенные в 2000 году, поддерживают эту форму защиты системных файлов, равно как и Windows XP и Windows Server 2003 . Его замена, Windows Resource Protection , была представлена в Windows Vista и Windows Server 2008 и использует другой метод защиты системных файлов от изменений.
- Учетно-свободный COM: Windows XP введен новый режим регистрации COM объекта под названием « Учетно-свободный COM ». Эта функция позволяет приложениям, которым необходимо установить объекты COM, сохранять всю необходимую информацию реестра COM в собственном каталоге приложения, а не в глобальном системном реестре. Таким образом, он предоставляет механизм для одновременной регистрации нескольких версий одной и той же DLL несколькими приложениями (Microsoft называет это « параллельной сборкой » [14] ). DLL-ада можно существенно избежать, используя COM без регистрации, единственное ограничение заключается в том, что для этого требуется как минимум Windows XP или более поздние версии Windows, и его нельзя использовать для серверов EXE COM или общесистемных компонентов, таких как MDAC , MSXML , DirectX или Internet Explorer .
- Поставка операционной системы с мощной системой управления пакетами, которая способна отслеживать зависимости DLL, поощрять использование диспетчера пакетов и препятствовать установке DLL вручную. Установщик Windows , входящий в состав Windows Me , Windows 2000 и всех более поздних версий, обеспечивает эту функцию.
- Наличие центральной базы данных или полномочий для разрешения конфликтов DLL и распространения программного обеспечения. Изменения в библиотеке могут быть отправлены в этот орган; таким образом, он может гарантировать сохранение совместимости в разработанных ветвях. Если какое-то более старое программное обеспечение несовместимо с текущей библиотекой, орган может предоставить для него интерфейс совместимости или связать старую версию как отдельный пакет.
- Если разработчикам программного обеспечения необходимо настроить библиотеку, и если выпуск основной библиотеки вряд ли будет включать необходимые им изменения, они могут отправить настроенную DLL для личного использования программы (обычно, поместив ее в частный каталог программы) или статически связать программа против настроенной библиотеки.
- Хотя библиотеки DLL лучше всего подходят для модульного построения приложений и компонентов системы, а также в качестве сторонних библиотек, их использование не обязательно во всех случаях в современных системах, где память больше не является ограничением. Например, если приложению нужна библиотека, которая больше нигде не будет использоваться, ее можно связать статически, без потери места и с увеличением скорости.
- Windows Vista и более поздние версии используют специальную службу TrustedInstaller для установки файлов операционной системы. Другие учетные записи пользователей, включая SYSTEM, не имеют доступа к перезаписи основных системных двоичных файлов. Windows 7 расширяет эту функциональность до некоторых важных частей реестра.
- Веб-приложения избегают многих параллельных проблем, выполняя основную часть кода на сервере и используя интерфейс браузера на клиенте.
Смотрите также
- Ад зависимости
- Портативное приложение
- Создатели портативных приложений
- JAR ад
Рекомендации
- ^ «Избегая ада DLL: введение метаданных приложения в Microsoft .NET Framework» . Microsoft. Октябрь 2000 г.
- ^ «Сводка статей о CTL3D.DLL в базе знаний службы поддержки Майкрософт» . Microsoft.
- ^ Распространение общего компонента среды выполнения C в Visual C ++ 2005 и Visual C ++ .NET .
- ^ KB 830490: Принтер HP Color LaserJet печатает только в оттенках серого или в черно-белом цвете на компьютере под управлением Windows 2000 SP4 .
- ^ Лесли Мюллер; Стив Уайт (июль 2005 г.). «Активация COM-компонентов без регистрации: пошаговое руководство» . Microsoft .
- ^ «Безопасная загрузка библиотек для предотвращения атак с предварительной загрузкой DLL» . Microsoft. 2011-06-11 . Проверено 19 июля 2011 .
- ^ Пфайффер, Тим (1998-06-01). "Windows DLL: угроза или угроза?" . Журнал доктора Добба. Архивировано из оригинала на 2010-08-07 . Проверено 7 июля 2010 .
- ^ Защита файлов Windows и Windows .
- ^ а б Андерсон, Рик (2000-01-11). «Конец ада DLL» . microsoft.com. Архивировано из оригинала на 2001-06-05 . Проверено 7 июля 2010 .
- ^ «Внедрение параллельного совместного использования компонентов в приложениях (расширено)» . Microsoft. Архивировано из оригинала 10 декабря 2006 года . Проверено 3 января 2013 года .
- ^ «Как мне поделиться данными в моей DLL с приложением или с другими DLL?» . Microsoft . Проверено 11 ноября 2008 .
- ^ «Безопасная загрузка библиотек для предотвращения атак предварительной загрузки DLL» . Microsoft . Проверено 16 фев 2013 .
- ^ Параллельные сборки (Windows)
Внешние ссылки
- Как выйти из ада DLL в Microsoft TechNet
- Упрощение развертывания и решение проблем с DLL с помощью .NET Framework на MSDN
- Как избежать ада DLL: введение метаданных приложения в Microsoft .NET Framework , Мэтт Пьетрек
- Доктор Добб на DLL Hell (подробности на LoadLibraryEx)
- Joel on Software Обсуждение
- Статья о DLL Hell