У меня есть плагиноподобная архитектура в программе, в которой реализации абстракции видео определены в общих библиотеках. У меня также есть общая статическая библиотека, используемая всеми из них:
- 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.