Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

На главную -> MyLDP -> Программирование и алгоритмические языки


Ulrich Drepper "Как писать разделяемые библиотеки"
Назад Оглавление Вперед

3.2. Обеспечение стабильности

Говоря о том, что стабильность интерфейса ABI является главной задачей сопровождения DSO, нужно определить, что означает стабильность. Для некоторых читателей может оказаться сюрпризом, что считать, что все, что работало раньше, должно продолжать работать в будущем, является наивным взглядом на проблему. Каждый, кто сталкивался с этим раньше, видит в этом взгляде проблему.

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

В качестве примера возьмем реализацию функции strtok в библиотеке времени выполнения языка C. Стандарт требует, чтобы при первом вызове strtok первый параметр не был пустым (т. е. не NULL). Но что произойдет, если первый вызов в качестве первого параметра будет иметь значение NULL? В этом случае поведение неопределено (в данном случае даже не определено в реализации). В некоторых реализациях в этом случае будет просто возвращаться NULL, поскольку это обычный побочный эффект возможной реализации. Но это не гарантируется. Вызов функции может также привести к сбою в работе приложения. Оба варианта являются допустимыми реализациями, но смена одной реализации на другую в процессе эксплуатации DSO будет причиной несовместимости.

Возникает вопрос: это на самом деле считается несовместимостью? На правильную программу это никогда не должно повлиять. Это влияет только на программы, которые не следуют документированному интерфейсу. И если в реализации делаются изменения, которые должны повысить эффективность (неважно, в каком смысле), то означает ли это, что из-за неправильных приложений нужно прекратить улучшать реализацию DSO. Это неприемлемо.

Поэтому при определении стабильности нужно в качестве базиса пользоваться документированным интерфейсом. Изменения в реализации не должны оказывать влияние на правильное использование интерфейсов; использования интерфейсов неопределенным образом не гарантируется. То же самое относится к использованию абсолютно недокументированных внутренних символов. Они вообще не должны использоваться. Хотя это определение стабильно широко признано, оно не означает, что следует избегать и не работать с изменениями, внесенными из-за изменений в реализации. Оно просто не нужно, если достижение стабильности связано с определенными затратами, что происходит почти всегда.

Одно дело не поддерживать стабильность для неопределенной функциональности, но что произойдет, если будут изменены некоторые документированные возможности? Это может произойти по различным причинам:

  • В реализации есть ошибка. В других реализациях получают другие результаты, и представляет интерес кросс-платформенная совместимость. Также может представлять интерес сохранение старого неправильного поведения.
  • Аналогичным образом, согласование со стандартами, пересмотр стандартов или практический опыт использования других реализаций может сулить выгоды в будущем и, следовательно, имеет смысл внести изменения.
  • Функциональность интерфейса расширяется или сокращается в зависимости от лежащих в основе базовых технологий. Например, внедрение более современных жестких дисков может позволить обрабатывать запросы, которые в предыдущих версиях обрабатываться не могли, и эти дополнительные запросы должны быть доступны через интерфейсы функций.

Если изменения не вносить, то это может привести к негативным последствиям. Слепое изменение кода, безусловно, имеет отрицательный результат. Внесение изменений и поддержка стабильности ABI требуют использовать контроль версий.

Такими несовместимыми изменениями в объекте DSO являются не только те изменения, которые могут вызвать проблемы. Добавление нового интерфейса не вызывает проблем для существующих приложений. Но если новое приложение использует новый интерфейс, оно столкнется с проблемами, если во время выполнения в наличии будет только старая версия DSO, в которой нет нового добавленного символа. Пользователь может это обнаружить, если принудительно заставит динамический компоновщик выполнить все перемещения во время загрузки, определив для этого переменную среды окружения LD BIND NOW с непустым значением перед тем, как он запустит приложение. Если используется старый объект DSO, работа динамического компоновщика будет прекращена с ошибкой. Но если принудительно заставлять выполнять перемещения, то это будет приводить к большим потерям в производительности (по этой причине были в первую очередь введены отложенные перемещения). Вместо этого, динамический компоновщик должен обнаруживать старую версию объекта DSO без выполнения таких перемещений.


Предыдущий раздел:   Следующий раздел:
Назад Оглавление Вперед