我试着更好地理解符号可见性.GCC Wiki(http://gcc.gnu.org/wiki/Visibility)有一节关于"C++异常问题".根据GCC Wiki,由于没有导出的异常,可能会出现运行时错误.没有编译时错误/警告的运行时错误是非常危险的,所以我试图更好地理解问题.我做了一些实验,但我仍然无法重现它.任何想法如何重现问题?
Wiki提到了三个库互相使用,所以我创建了三个小库.
我运行以下命令:
没有vtable的异常类(按预期工作):
make
./dsouser
Run Code Online (Sandbox Code Playgroud)
使用vtable的异常类但它不会导出(甚至不编译):
make HAS_VIRTUAL=1
Run Code Online (Sandbox Code Playgroud)
异常类导出vtable(按预期工作):
make HAS_VIRTUAL=1 EXCEPTION_VISIBLE=1
./dsouser
Run Code Online (Sandbox Code Playgroud)
Makefile文件:
CXX=g++-4.7.1
CFLAGS=-ggdb -O0 -fvisibility=hidden
ifdef EXCEPTION_VISIBLE
CFLAGS+=-DEXCEPTION_VISIBLE
endif
ifdef HAS_VIRTUAL
CFLAGS+=-DHAS_VIRTUAL
endif
all: dsouser
libmydso.so: mydso.cpp mydso.h
$(CXX) $(CFLAGS) -fPIC -shared -Wl,-soname,$@ -o $@ $<
libmydso2.so: mydso2.cpp mydso.h mydso2.h libmydso.so
$(CXX) $(CFLAGS) -L. -fPIC -shared -Wl,-soname,$@ -o $@ $< -lmydso
libmydso3.so: mydso3.cpp mydso.h mydso2.h mydso3.h libmydso2.so
$(CXX) $(CFLAGS) -L. -fPIC -shared -Wl,-soname,$@ -o $@ $< -lmydso -lmydso2
dsouser: dsouser.cpp …Run Code Online (Sandbox Code Playgroud) 我正在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() {}
Run Code Online (Sandbox Code Playgroud)
警告消息可以在这个小例子中重现,但当然命名空间应该在应用程序中的另一个类的库中.
$ 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]
Run Code Online (Sandbox Code Playgroud)
由于我理解符号可见性,隐藏命名空间应该与使用-fvisibility = hidden具有非常相似的效果,但我从未使用后者获得类似的警告.我看到当我将-fvisibility = hidden传递给应用程序时,应用程序中的类也将被隐藏,所以我不会收到警告.但是当我没有通过选项时,标题中的符号似乎都不会被编译器隐藏,所以我不会再收到警告.
这条警告信息的建议是什么?这是一个严重的问题吗?在哪种情况下会导致任何问题?如何隐藏命名空间与fvisibility = hidden不同?