使用 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::string
和 std::__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 符号从何而来?的主要内容,如果未能解决你的问题,请参考以下文章
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版本太低