为什么我的std :: filesystem使用SO暴露了std :: filesystem符号?

时间:2019-09-13 20:40:39

标签: c++ gcc c++17 nm

我正在Linux上构建共享库,并且已配置项目以使用-fvisibility=hidden进行编译,并使用__attribute__ (( __visibility__ ("default")))手动添加到要导出的符号中。以下虚拟文件足以说明:

#include <experimental/filesystem>
#include <iostream>

namespace fs = std::experimental::filesystem;

__attribute__((__visibility__("default"))) void foo() { std::cout << "foo\n"; }

void bar() { std::cout << "bar\n"; }

// void baz() { std::cout << fs::current_path().string() << std::endl; }

然后使用:

g++ -shared -o dummy.so -fPIC dummy.cpp -lstdc++fs -fvisibility=hidden

并运行nm -CD dummy.so | grep " T "来检查导出的符号(在手册页的文本部分中定义的符号)。

  • 按原样,您只会看到foo被导出:这就是我所期望的。
  • 如果删除-fvisibility=hidden,将看到同时导出的foobar。还可以。
  • 如果取消注释baz(使用std :: filesystem的函数),则无论是否有-fvisibility=hidden,您都会看到导出的大量文件系统符号。像这样:
000000000003b110 T std::filesystem::__cxx11::directory_iterator::operator*() const
000000000003a930 T std::filesystem::__cxx11::recursive_directory_iterator::depth() const
000000000003a980 T std::filesystem::__cxx11::recursive_directory_iterator::operator*() const
0000000000034bb0 T std::filesystem::__cxx11::path::parent_path() const
0000000000032870 T std::filesystem::__cxx11::path::has_filename() const

依此类推-仅显示std :: filesystem或std :: experimental :: filesystem中的符号。

看看libstdc ++ fs_path.h标头,我假设这种可见性是由namespace std _GLIBCXX_VISIBILITY(default)行触发的。但是,文件系统并不是库中使用的唯一标准库工具(真正的库工具或该虚拟库工具):也使用了许多其他工具,并且在此视图中都没有出现。

我了解为什么在编译实际的标准库SO时这些符号应该可见,但是为什么从仅使用标准库的库中“导出”这些符号呢?而且,为什么只导出文件系统符号?我可以在不删除std :: filesystem使用的情况下解决此问题吗?

(我的环境是Debian Buster x64。无论我使用Clang还是GCC,这似乎都发生了,并且系统编译器是GCC 8.3.0及其相关的libstdc ++。)

0 个答案:

没有答案