Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

Проблема хрупкого бинарного интерфейса или FBI является недостатком некоторых компиляторов объектно-ориентированного языка программирования , в которых внутренние изменения в базовой библиотеке классов могут привести к прекращению работы дочерних библиотек или программ. Это пример нестабильности программного обеспечения .

Эту проблему чаще называют проблемой хрупкого базового класса или FBC ; однако этот термин имеет более широкий смысл.

Причина [ править ]

Проблема возникает из-за "ярлыка", используемого с компиляторами для многих распространенных объектно-ориентированных (OO) языков, особенности дизайна, которая сохранялась, когда OO-языки развивались из более ранних не-объектно-ориентированных языков программирования, таких как C и Pascal .

В этих языках не было объектов в современном понимании, но была аналогичная конструкция, известная как запись (или «структура» в C), которая содержала различную связанную информацию в одном фрагменте памяти. Доступ к частям в конкретной записи осуществлялся путем отслеживания начального местоположения записи и знания смещения от этой начальной точки до рассматриваемой части. Например, запись «человека» может иметь имя, фамилию и отчество, чтобы получить доступ к инициалу, записанному программистом, thisPerson.middleInitialкоторый компилятор превращает во что-то вроде a = location(thisPerson) + offset(middleInitial). Современные процессоры обычно включают инструкции для этого общего вида доступа.

Когда впервые разрабатывались компиляторы объектно-ориентированного языка, использовалась большая часть существующей технологии компилятора, а объекты строились на основе концепции записи. В этих языках объекты упоминались по их начальной точке, а доступ к их общедоступным данным, известным как «поля», осуществлялся через известное смещение. Фактически, единственным изменением было добавление к записи другого поля, которое настроено так, чтобы указывать на неизменяемую таблицу виртуальных методов для каждого класса, так что запись описывает как свои данные, так и методы (функции). При компиляции смещения используются для доступа как к данным, так и к коду (через таблицу виртуальных методов).

Симптомы [ править ]

Это приводит к проблемам в больших программах, когда они построены из библиотек . Если автор библиотеки изменяет размер или макет общедоступных полей в объекте, смещения теперь недействительны, и программа больше не будет работать. Это проблема ФБР.

Хотя можно ожидать, что изменения в реализации вызовут проблемы, коварство ФБР заключается в том, что на самом деле ничего не изменилось, а только макет объекта, который скрыт в скомпилированной библиотеке. Можно было бы ожидать , что если один изменения doSomethingв doSomethingElseтом , что это может вызвать проблемы, но в этом случае один может вызвать проблемы без изменения doSomething, она может быть вызвана так же легко , как перемещение строк исходного кода вокруг для ясности. Хуже того, программист практически не может контролировать результирующий макет, сгенерированный компилятором, что делает эту проблему почти полностью скрытой от просмотра.

В сложных объектно-ориентированных программах или библиотеках классы самого высокого уровня могут быть унаследованы от десятков классов. Каждый из этих базовых классов также может быть унаследован сотнями других классов. Эти базовые классы хрупки, потому что небольшое изменение одного из них может вызвать проблемы для любого класса, который наследуется от него напрямую или от другого класса, который наследует. Это может привести к тому, что библиотека рухнет, как карточный домик, поскольку многие классы будут повреждены одним изменением базового класса. Проблема может не быть замечена при написании изменений, если дерево наследования сложное. Действительно, разработчик, изменяющий базовый класс, обычно не знает, какие классы, разработанные другими, его используют.

Решения [ править ]

Языки [ править ]

Одно из решений проблемы хрупкого двоичного интерфейса - написать язык, который знает, что проблема существует, и не позволяет ей случиться. Большинство ОО-языков, написанных на заказ, в отличие от языков, созданных на основе более ранних языков, создают все свои таблицы смещения во время загрузки. В этот момент будут «замечены» изменения в макете библиотеки. Другие объектно-ориентированные языки, такие как Self , создают все во время выполнения, копируя и изменяя объекты, найденные в библиотеках, и поэтому на самом деле не имеют базового класса, который может быть хрупким. Некоторые языки, такие как Java , содержат обширную документацию о том, какие изменения можно безопасно внести, не вызывая проблем у ФБР.

Другое решение - записать промежуточный файл со списком смещений и другой информации со стадии компиляции, известной как метаданные. Затем компоновщик использует эту информацию для исправления себя, когда библиотека загружается в приложение. Платформы, такие как .NET, делают это.

Однако рынок выбрал языки программирования, такие как C ++ , которые действительно «зависят от позиции» и, следовательно, демонстрируют ФБР. В этих случаях есть еще ряд решений проблемы. Один из них возлагает бремя на автора библиотеки, заставляя его вставлять несколько объектов-заполнителей на случай, если им понадобится добавить дополнительные функции в будущем (это можно увидеть в структурах, используемых в библиотеке DirectX ). Это решение работает хорошо, пока у вас не закончатся эти манекены - и вы не хотите добавлять слишком много, потому что это занимает память.

Objective-C 2.0 предоставляет устойчивые переменные экземпляра , имея дополнительный уровень косвенности, например, доступ к переменным экземпляра.

Другое частичное решение - использовать шаблон «Мост» , иногда известный как « Pimpl » («Указатель на реализацию»). Рамки Qt является примером такой реализации в. Каждый класс определяет только один член данных, который является указателем на структуру, содержащую данные реализации. Размер самого указателя вряд ли изменится (для данной платформы), поэтому изменение данных реализации не влияет на размер общедоступной структуры. Однако это не позволяет избежать других критических изменений, таких как введение виртуальных методов в класс, у которого их нет, или изменение графа наследования.

Линкеры [ править ]

Другое решение требует более умного компоновщика. В исходной версии Objective-C формат библиотеки допускал несколько версий одной библиотеки и включал некоторые функции для выбора правильной библиотеки при вызове. Однако это не всегда было необходимо, потому что смещения были нужны только для полей, поскольку смещения методов собирались во время выполнения и не могли вызвать FBI. Поскольку методы имеют тенденцию меняться чаще, чем поля, у ObjC изначально было мало проблем с ФБР, и те, которые он делал, можно было исправить с помощью системы управления версиями. В Objective-C 2.0 добавлена ​​«современная среда выполнения», которая также решила проблему ФБР для полей. Кроме того, язык TOM использует смещения, собранные во время выполнения, для всего, что делает невозможным ФБР.

Другим решением является использование статических вместо динамических библиотек, где это возможно, поскольку в этом случае библиотеку нельзя изменить без перекомпиляции приложения и обновления используемых смещений. Однако у статических библиотек есть свои собственные серьезные проблемы, такие как бинарный файл большего размера и невозможность использовать новые версии библиотеки «автоматически» по мере их появления.

Архитектура [ править ]

В этих языках проблема уменьшается за счет принудительного одиночного наследования (поскольку это снижает сложность дерева наследования) и за счет использования интерфейсов вместо базовых классов с виртуальными функциями , поскольку сами интерфейсы не содержат кода, а только гарантия того, что каждый сигнатура метода, объявленная интерфейсом, будет поддерживаться каждым объектом, реализующим интерфейс.

Метод распространения [ править ]

Вся проблема рушится, если доступен исходный код библиотек. Тогда простая перекомпиляция сделает свое дело.

См. Также [ править ]

  • Хрупкий базовый класс

Внешние ссылки [ править ]

  • Статья BeOS о проблеме и способах их решения