#c #macos #gcc #clang
Вопрос:
Я компилирую этот код в AppleClang 12.0.5, используя команду:
clang -O2 -g -fvisibility=hidden -std=c 17 -Wpedantic -c sharedlib.cpp
и я проверяю список символов в объектном файле с помощью:
nm -om sharedlib.o | c filt | grep "typeinfo for"
Сам код (sharedlib.cpp):
namespace Foo { template lt;class Tgt; class BarHidden; class BarExported; } typedef Foo::BarHiddenlt;doublegt; BarHiddenTypedef; typedef Foo::BarExported BarExportedTypedef; namespace Foo { templatelt;typename Tgt; class __attribute__((visibility("default"))) BarHidden { public: virtual ~BarHidden(){}; }; class __attribute__((visibility("default"))) BarExported { public: virtual ~BarExported(){}; }; } void __attribute__((visibility("default"))) Throw() { // throw Foo::BarExported(); // weak external typeinfo for Foo::BarExported // throw Foo::BarHiddenlt;intgt;(); // weak external typeinfo for Foo::BarHiddenlt;intgt; throw Foo::BarHiddenlt;doublegt;(); // weak private external typeinfo for Foo::BarHiddenlt;doublegt; }
Может ли кто-нибудь объяснить, почему 1-й и 2-й броски оставляют видимым внешний символ typeinfo (ожидаемый), но третий бросок оставляет символ typeinfo со скрытой видимостью? Похоже, что typedef создает экземпляры Foo::BarHidden с неверным атрибутом видимости (я виню typedef, потому что компилятор создает видимый typeinfo, если я удаляю BarHiddenTypedef typedef), но ожидается ли такое поведение? Можно ли его отключить? У меня огромная кодовая база, которая потенциально может иметь проблемы такого рода, и я хочу быть уверен, что все типы моих dylib видны.
Комментарии:
1. Вам придется спросить людей, которые написали компилятор, который вы используете.
__attribute__((visibility("default")))
не является стандартным C .2. Я согласен, но, может быть, кто-то здесь знает причину такой реализации компилятора.
3. Я думаю, это потому, что typedef объявляет неявный экземпляр (который является неполным типом, поскольку объявление класса еще не было замечено). Выражение throw не создает экземпляр из объявления класса при обработке выражения throw, потому что оно уже было создано. Попробуйте переместить символы ввода в после того, как будут определены классы шаблонов.
4. @1201ProgramAlarm, конечно, это работает после того, как я перемещаю символы ввода после определения класса или после объявления, которое объявлено с видимостью по умолчанию. Проблема в том, что в огромном проекте невозможно держать такие вещи под контролем, когда все делают прямые объявления в заголовочных файлах, которые включаются в случайном порядке.