Я экспериментирую с видимостью символов C++ в Linux и gcc. Похоже, что предпочтительный способ - использовать -fvisibility = hidden и экспортировать используемые символы один за другим в соответствии с вики-страницей видимости gcc (http://gcc.gnu.org/wiki/Visibility). Моя проблема заключается в том, что библиотеки много не справляются с этим, они забывают явно экспортировать символы, что является серьезной проблемой. После нескольких исправленных ошибок даже некоторые части повышения могут все еще быть затронуты. Конечно, эти ошибки должны быть исправлены, но до этого я хотел бы использовать «безопасный» способ скрыть как можно больше символов.Видимость символов и пространство имен
Я придумал решение: я помещаю все символы в пространство имен, и на этом я использую атрибут hide hide и экспортирую открытый интерфейс, таким образом меня могут затронуть только мои символы.
Проблема заключается в том, что я получил предупреждение, когда я скомпилировал что-то против этой библиотеки для каждого класса, который я не экспортировал, и использую в приложении как поле класса.
namespace MyDSO __attribute__ ((visibility ("hidden"))) {
struct Foo {
void bar() __attribute__ ((visibility ("default"))) {}
};
}
struct Bar {
MyDSO::Foo foo;
};
int main() {}
предупреждающее сообщение может быть воспроизведен в этом маленьком примере, но, конечно, пространство имен должно быть в библиотеке другого класса в приложении.
$ gcc-4.7.1 namespace.cpp -o namespace
namespace.cpp:7:8: warning: ‘Bar’ declared with greater visibility than the type of its field ‘Bar::foo’ [-Wattributes]
Как я понимаю, видимость символа, скрывается пространство имен должно быть достаточно, чтобы подобный эффект с помощью -fvisibility = скрытый, но я никогда не получал подобные предупреждения с помощью последнего. Я вижу, что когда я передаю -fvisibility = hidden в приложение, класс в приложении также будет скрыт, поэтому я не получу предупреждение. Но когда я не передаю этот параметр, ни один из символов в заголовках не будет скрыт от компилятора, поэтому я не получу предупреждение снова.
Что представляет собой предложение этого предупреждения? Это серьезная проблема? В каких ситуациях это может вызвать проблемы? Как скрыть пространство имен отличается от fvisibility = hidden?
Спасибо за подробный ответ. Просто для любопытства, меня интересуют, какие символы нужен компилятору, который не может быть сгенерирован? Насколько я знаю в тривиальных классах, может генерироваться даже типinfo. При использовании vis = hidden вы не получите предупреждения, даже если вы скрываете символы, которые не должны быть скрыты, вы просто получаете неопределенную ошибку символа от компоновщика. Использование скрытого пространства имен gcc может обнаружить проблему. Возможно, есть законное использование, чтобы экспортировать только некоторые символы в классе, но gcc все равно выдает предупреждение. Модули C++ Дуга Грегора очень интересны, мне понравилась его презентация, спасибо, что поделились ею. – VargaD
Короче говоря, typeinfo для любого класса с виртуальным всегда испускается, тогда как typeinfo для классов без него испускается только тогда, когда используется typeid() или что-то, что его использует (исключение catch, dynamic_cast <> и т. Д.). Кроме того, большинство компиляторов испускают две или более реализаций конструктора для каждого указанного конструктора программы, и в генерации деструкторов также есть какая-то магия. Короче говоря, -fvisibility = hidden скрывает лот, и ваш метод скроет только указанный программистом материал, а не волшебные внутренние элементы. Большая часть этого начинает упрощаться с C++-модулями, хотя и не решена. Niall –