我正在试验Linux和gcc上的C++符号可见性。似乎首选的方法是使用-fvisibility = hidden,并根据Visibility gcc wiki页面(http://gcc.gnu.org/wiki/Visibility)逐个导出使用的符号。 我的问题是,很多库不处理这个好,他们忘记明确的出口符号,这是一个严重的问题。在几个固定的错误之后,即使某些提升的部分仍可能受到影响。当然,这些错误应该是固定的,但在此之前我想用一种“安全”的方式尽可能多地隐藏符号。符号可见性和名称空间
我想出了一个解决办法:我把命名空间中的所有符号和我使用该符号隐藏属性和导出公共接口,这样,只有我的符号可能会受到影响。
的问题是,我得到了一个警告信息时,我对编译该库为每一个我还没有出口类的东西,我在应用程序类字段使用。
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不同?
感谢您的详细解答。只是为了好奇,我对编译器需要哪些不能生成的符号感兴趣?据我所知,在平凡的类甚至可以生成typeinfo。当使用vis = hidden时,即使隐藏了不应该隐藏的符号,也不会收到警告,您只需从链接器获取未定义的符号错误。使用隐藏的命名空间gcc可以检测到问题。也许有合法用途只能导出某个类中的某些符号,但gcc无论如何都会发出警告。 Doug Gregor的C++ Modules非常有趣,我喜欢他的演讲,感谢你分享它。 – VargaD 2013-03-25 17:50:04
简而言之,任何具有虚拟类的类型信息总是被发出,而类型信息只有在typeid()或使用它的东西(异常捕获,dynamic_cast <>等)被使用时才会被发出。此外,大多数编译器为每个程序指定的构造函数发出两个或更多的构造函数实现,并且在析构函数生成中也有一些魔力。总之,-fvisibility = hidden隐藏了很多,你的方法只会隐藏程序员指定的东西而不是魔法内部。大部分这些开始变得更容易与C + +模块,虽然没有解决。 Niall – 2013-03-31 21:43:34