Передовые практики для написания динамических библиотек C [DSO] (двоичная совместимость + управление памятью) - PullRequest
23 голосов
/ 28 августа 2011

У меня есть некоторый опыт написания библиотек на Си, но я никогда не читал никаких формальных документов, описывающих хорошие практики при написании таких библиотек.Мой вопрос касается в основном двух тем:

  1. Как поддерживать двоичную совместимость?(Я слышал об идиоме pImpl, d-указатель)
  2. Как проектировать интерфейсы, которые остаются обратно совместимыми?

Главное о двоичной совместимости, которую я вижу из моегоисследование заключается в том, что я могу сделать библиотеки двоично-совместимыми, используя идиому pImpl, но изменение структуры / добавление новых элементов данных и т. д. может повлиять на их двоичную совместимость даже при использовании pImpl.Кроме того, есть ли способ добавить новые методы / функции в библиотеку, фактически не нарушая бинарную совместимость?Я предполагаю, что добавление этих вещей изменило бы размер, расположение библиотеки, таким образом нарушая совместимость.

Есть ли инструмент для проверки двоичной совместимости?

Я уже читал эти статьи.Есть ли другие документы, которые я могу просмотреть?

http://en.wikipedia.org/wiki/Opaque_pointer

http://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C++

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

Ответы [ 4 ]

21 голосов
/ 28 августа 2011

Ключевые проблемы совместимости:

  • сигнатуры функций
  • формат любых данных, доступных как библиотеке, так и вызывающей стороне
  • глобальные переменные в библиотеке, к которым обращается вызывающий
  • код библиотеки, который заканчивается в вызывающей программе из-за макросов / встроенных функций в заголовках
  • #define / enum постоянные значения в общих заголовках

Итак, лучший список рекомендаций, которые я могу дать:

  • Никогда не меняйте подпись (типы возврата / аргумента) любого открытого интерфейса. Если вам нужно расширить интерфейс, вместо этого добавьте новую функцию, которая принимает больше аргументов (например, dup против dup2 или wait против waitpid).
  • Насколько это возможно, используйте указатели на полностью инкапсулированные непрозрачные объекты данных и даже не раскрывайте определение таких структур в публичных заголовках (делайте их неполными struct типов).
  • Когда вы хотите поделиться структурой, договоритесь, чтобы вызывающая сторона никогда не объявляла переменные этого типа структуры, а вместо этого вызывала явные функции allocate / free в библиотеке. Никогда не меняйте тип существующих участников и не удаляйте существующих; вместо этого добавляйте новых членов только в конце структуры.
  • Не выставлять глобальные переменные из библиотек, точка. Если вы не понимаете «перемещение копий», лучше не спрашивать, почему. Только не делай этого.
  • Не помещайте встроенные функции или макросы, содержащие код, в публичные заголовки вашей библиотеки, если только не используется документированный, открытый интерфейс, который будет оставаться постоянным. Если они тыкнут во внутренние органы непрозрачных данных, они вызовут проблемы, когда вы решите изменить внутренние устройства.
  • Не перенумеровывать существующие #define / enum константы. Добавляйте только новые константы с ранее не использованными значениями.

Если вы будете следовать этим рекомендациям, я думаю, что вы охвачены как минимум на 95%.

5 голосов
/ 28 августа 2011

Существует ли инструмент для проверки двоичной совместимости?

ABI Compliance Checker - инструмент для проверки обратной двоичной совместимости совместно используемой библиотеки C / C ++ (DSO)).

Есть ли другие документы, которые я могу просмотреть?

См. Этот длинный список статей о двоичной совместимости совместно используемых библиотек.

Как проектировать интерфейсы, которые остаются обратно совместимыми?

Использование зарезервированных / заполненных полей - это общий метод сохранения совместимости C библиотеки.Но есть и много других.

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

Добавленные функции C не нарушают обратную двоичную совместимость DSO на Linux и Mac,То же самое верно для Windows и Symbian, но вы должны добавлять новые функции только в конец файла .DEF.Прямая совместимость всегда нарушается добавленными функциями.

Добавленные C ++ методы нарушают бинарную совместимость тогда и только тогда, когда они virtual или pure-virtual единиц, потому что расположение v-таблицы может измениться.Но ваш вопрос, похоже, касается только C библиотек.

3 голосов
/ 29 августа 2011

С точки зрения документации, Как писать общие библиотеки от Ульриха Дреппера является обязательным для прочтения.

3 голосов
/ 28 августа 2011

Пара вещей, которые нужно добавить к тому, что сказал Р.:

Поскольку кажется, что вы говорите о C ABI, а не о C ++ ABI:

изменение структуры / добавление новых элементов данных и т. Д. Может повлиять на его двоичную совместимость даже при использовании pImpl

Этого не должно быть при использовании pIMpl - если внешние пользователи объекта имеют только непрозрачный указатель / дескриптор объекта и только библиотека имеет дело с внутренними элементами структуры, то по определению то, что имеет дело с внутренними структурами совместим с ним.

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

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

...