我正在尝试在 Linux 和 gcc 上使用 C++ 符号可见性。似乎首选的方法是使用 -fvisibility=hidden,并根据 Visibility gcc wiki 页面(http://gcc.gnu.org/wiki/Visibility)一个接一个地导出使用的符号。我的问题是许多库处理得不好,他们忘记显式导出符号,这是一个严重的问题。在修复了几个 bug 之后,甚至 boost 的某些部分仍然可能受到影响。当然这些错误应该被修复,但在此之前我想使用一种“安全”的方式来隐藏尽可能多的符号。
我想出了一个解决方案:我将所有符号放在命名空间中,并在其上使用符号隐藏属性并导出公共接口,这样只有我的符号会受到影响。
问题是,当我为每个尚未导出的类并在应用程序中用作类字段时针对该库编译某些内容时,我收到了一条警告消息。
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=hidden 具有非常相似的效果,但使用后者我从未收到类似的警告。我看到当我将 -fvisibility=hidden 传递给应用程序时,应用程序中的类也将被隐藏,所以我不会收到警告。但是,当我不传递该选项时,标头中的任何符号都不会被编译器隐藏,因此我不会再次收到警告。
这个警告信息的建议是什么?这是一个严重的问题吗?在哪些情况下这会导致任何问题?隐藏命名空间与 fvisibility=hidden 有何不同?