使用 LLVM 的 libc++ 时,__1 符号从何而来?

Posted

技术标签:

【中文标题】使用 LLVM 的 libc++ 时,__1 符号从何而来?【英文标题】:Where does the __1 symbol come from when using LLVM's libc++? 【发布时间】:2015-05-31 08:25:17 【问题描述】:

我看到很多问题,例如 Apple Mach-O Linker (Id) Error 和 Undefined symbols in cryptopp at ios 64-bit project。问题通常描述为:

Undefined symbols for architecture i386:
  "std::__1::basic_ostream<char, std::__1::char_traits<char> >::flush()", referenced from:
      cv::gpu::error(char const*, char const*, int, char const*) in opencv2(gpumat.o)

问题通常归结为混合/匹配-stdlib=libc++(LLVM C++ 运行时)和-stdlib=libstdc++(GNU C++ 运行时)。 LLVM C++ 运行时 (libc++) 有一个 __1 装饰符号,但 GNU C++ 运行时 libstdc++ 缺少其名称中的 __1 符号。对于看起来具有相同名称的符号(如std::string),它会导致链接器出现问题。

使用 LLVM 的 libc++ 时,__1 符号从何而来?

为什么使用gnu 命名空间和llvm 命名空间没有解决问题?


这是一个相关问题:libc++ - stop std renaming to std::__1?。但它有点忽略了不会发生重命名的问题。

【问题讨论】:

它是 libc++ 用于版本控制的内联命名空间。 【参考方案1】:

它来自 C++11 内联命名空间

libc++ 有类似的东西

namespace std 
    inline namespace __1 
        ....

更多What are inline namespaces for?

【讨论】:

谢谢@Severin。这是一个有趣的链接。所以 如果 我使用了 C++11 编译器,std::stringstd::__1::string 的问题会消失,因为编译器会理解内联命名空间?或者如果我使用-std=c++03,问题就会消失,因为不会使用内联命名空间? (到目前为止,我一直在告诉人们使用 LLVM 运行时或 GNU 运行时编译所有内容。 @jww 我相信两个编译器(GCC 和 clang)都理解内联命名空间。问题在于声明与定义。如果你使用 libc++ 头文件,你会得到带有 std::__1:: 前缀的声明,比如 std::__1::string 等。如果你使用 GNU libstdc++ 头文件,你会得到声明 std::string 等。但是你有从 libstdc++.a/.so 或 libc++.a/.so 中获取定义。由于每个库都使用自己的头文件进行编译,因此定义也带有相同的前缀。待续…… 因此,如果您从 libc++ 标头中选择声明(带有 std::__1:: 前缀)但尝试使用来自 libstdc++ 的定义(带有 std:: 前缀),您将收到链接器错误 - 定义不多。好事,我认为,调试可能是一场噩梦。所以我想说如果你使用 GNU 工具链,链接到 libstdc++,如果 clang - 链接到 libc++ 只是要清楚 - 这些前缀在 .o/.a/.so 中的已编译代码中的名称混乱。在源代码中,您会看到/使用 std::string。

以上是关于使用 LLVM 的 libc++ 时,__1 符号从何而来?的主要内容,如果未能解决你的问题,请参考以下文章

LLVM libc++的RISCV支持

CodeTyphonGCC编译出现 undefined reference to `__libc_csu_init' 和 `__libc_csu_fini'的解决方法

Android兼容之libc++_shared.so库冲突方案

glibc升级GLIBC_2.14,一定不要mv libc.so.6 libc.so.6_bak……

在 Xcode 4 (LLVM GCC) 中使用 _mm_shuffle_ps 时可能出现 OpenMP + SSE 错误

CentOS “/lib64/libc.so.6: version `GLIBC_2.14′ not found”系统glibc版本太低