Переходная символьная видимость в C ++ - PullRequest
0 голосов
/ 24 октября 2019

У меня есть плагиноподобная архитектура в программе, в которой реализации абстракции видео определены в общих библиотеках. У меня также есть общая статическая библиотека, используемая всеми из них:

  • myProgram (исполняемый файл) -> ссылки на libutil (статические)
  • libFoo (общие библиотеки) -> ссылки на libutil(статические)
  • libBar (разделяемая библиотека) -> Ссылки на libutil (статические)

myProgram будет динамически (во время выполнения) загружать ровно один из libFoo или libBar.

Кроме того, в libutil есть класс Log, который имеет в своей публичной части включение в интерфейс класса IWriter, а в его реализации - включение в конкретный класс, производный от IWriter с именем StdStreamWriter.

Этот класс Log использует и myProgram, и разделяемые библиотеки. Совместно используемые библиотеки также компилируются с -fvisibility=hidden, как это принято в настоящее время (например, Boost проделал значительную работу для выполнения этой работы)

Теперь проблема: с ASAN я получаю ошибку ODR:

РЕЗЮМЕ: AddressSanitizer: нарушение odr: global 'vtable for StdStreamWriter' в /path/to/StdStreamWriter.cpp

Я решил подобные ошибки, украсив класс с помощью BOOST_SYMBOL_VISIBLE like: class BOOST_SYMBOL_VISIBLE StdStreamWriter : public IWriter.

Это делает виртуальную таблицу класса "экспортированной", чтобы среда выполнения могла соответствовать виртуальным таблицам при загрузке общей библиотеки и НЕ создавала другую, которая вызывала бы сообщение о нарушении ODR.

Однако здесь это явно не работает.

Я предполагаю, что проблема в том, что заголовок класса никогда не включается в libFoo / libBar, поэтому при компиляции разделяемой библиотеки -fvisibility=hidden также действует для этогокласс, вызывающий экспорт vtable в not .

Однако нет смысла включать заголовок класса где-либо в разделяемые библиотеки, так каккод не использует этот класс напрямую (только через класс Log, где использование скрыто в реализации)

Возможно ли в любом случае сделать настройку видимости класса в статической библиотеке "транзитивной", чтобыэтот класс также «виден» в разделяемых библиотеках, связывающих этот класс / статическую библиотеку?

Использование Clang ++ 8 в Linux Mint 19.2.

...