【问题标题】:Taking pointer to member std::string::size fails to link with libc++ but works with libstdc++将指针指向成员 std::string::size 无法与 libc++ 链接,但可与 libstdc++ 一起使用
【发布时间】:2015-03-29 01:23:14
【问题描述】:

我正在进行一个需要使用 libc++ 的项目。我想出了以下问题:

当我尝试编译以下代码时:

#include <string>
int main()
{
    std::string::size_type (std::string::*function)() const = &std::string::size;
    return 0;
}

我收到以下错误:

ld:未找到架构 x86_64 的符号

如果我使用 libstdc++ 而不是 libc++,我不会收到任何错误,因此问题应该与 libc++ 有关。

下面的完整输出:

clang++ --stdlib=libc++ -v main.cpp 
Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.1.0
Thread model: posix
 "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" -cc1 -triple x86_64-apple-macosx10.10.0 -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -main-file-name main.cpp -mrelocation-model pic -pic-level 2 -mdisable-fp-elim -masm-verbose -munwind-tables -target-cpu core2 -target-linker-version 241.9 -v -resource-dir /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.0 --stdlib=libc++ -fdeprecated-macro -fdebug-compilation-dir /Users/filipe/Downloads -ferror-limit 19 -fmessage-length 197 -stack-protector 1 -mstackrealign -fblocks -fobjc-runtime=macosx-10.10.0 -fencode-extended-block-signature -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -vectorize-slp -o /var/folders/8k/34ll5dcj3c5c9sph_bwk1zr00000gn/T/main-5b89bb.o -x c++ main.cpp
clang -cc1 version 6.0 based upon LLVM 3.5svn default target x86_64-apple-darwin14.1.0
ignoring nonexistent directory "/usr/include/c++/v1"
#include "..." search starts here:
#include <...> search starts here:
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1
 /usr/local/include
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.0/include
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
 /usr/include
 /System/Library/Frameworks (framework directory)
 /Library/Frameworks (framework directory)
End of search list.
 "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld" -demangle -dynamic -arch x86_64 -macosx_version_min 10.10.0 -o a.out /var/folders/8k/34ll5dcj3c5c9sph_bwk1zr00000gn/T/main-5b89bb.o -lc++ -lSystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.0/lib/darwin/libclang_rt.osx.a
Undefined symbols for architecture x86_64:
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::size() const", referenced from:
      _main in main-5b89bb.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

【问题讨论】:

  • 你能添加你正在编译的命令行吗?根据 Shafik 的回答,它可能是编译器错误。但我仍然对编译器调用感兴趣。
  • 我猜接近的选民在 coliru 上尝试过这个并且无法重现,不过评论会有所帮助。
  • @jww 我使用的命令在完整输出上:clang++ --stdlib=libc++ -v main.cpp

标签: c++ stdstring libc++ missing-symbols


【解决方案1】:

这看起来像这个线程的libc++ 错误:_LIBCPP_INLINE_VISIBILITY and std::string::length 正在做类似的事情,Howard Hinnant 的回应是:

我认为这是由于编译器之间的交互不佳 外部模板和 __attribute__ ((__always_inline__))。如果 std::string 没有声明为外部模板,那么编译器将 勾勒出一个 size() 成员,你不会得到这个链接错误。

在我看来,clang 不应该假设 extern 模板具有 内联成员的定义,尤其是那些标记的 always_inline,事实上它确实是一个clang错误,导致 您看到的链接错误。

在 libc++ 中使用 always_inline 的基本原理是控制 libc++ 的 ABI。过去我看过编译器使用不同的 在制作内联/大纲时从发布到发布的启发式方法 决定。这可能会导致代码被静默添加和删除 从一个dylib。通过使用 always_inline,我告诉 编译器永远不会将该代码添加到 libc++.dylib 二进制文件中。

libc++ 定义和使用的每个宏都可以被覆盖。

_LIBCPP_INLINE_VISIBILITY 控制内联函数的属性,默认为:

#ifndef _LIBCPP_INLINE_VISIBILITY
#define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__visibility__("hidden"), __always_inline__))
#endif

您可以通过以下方式关闭此功能:

-D_LIBCPP_INLINE_VISIBILITY=""

外部模板通过以下方式完成:

#ifndef _LIBCPP_EXTERN_TEMPLATE
#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
#endif

后一种更难“关闭”。咒语是:

-D'_LIBCPP_EXTERN_TEMPLATE(...)='

使用这些解决方法中的任何一种(或两种)都会使您的链接静音 错误。但是针对clang的错误报告可能是一个更好的长期 解决方案。

我无法在coliru 上重现此问题,但我可以在wandbox 上重现此问题,并使用使用-O2 标志的优化使问题消失。我无法让 wandbox 接受上面建议的 -D 选项,所以不确定这是否有效。

在我的本地机器上,霍华德的解决方案有效:

clang++ -D_LIBCPP_INLINE_VISIBILITY="" -D'_LIBCPP_EXTERN_TEMPLATE(...)='

我还没有找到错误报告,如果我没有找到,提交一份可能是有意义的。

【讨论】:

  • 这是很好的信息。它使我能够找到有关外部模板的更多详细信息。谢谢!
【解决方案2】:

在查看了 Shafik Yaghmour 的信息后,我找到了一个不需要修改编译标志的解决方案。

解决方案是强制编译器实例化 extern 模板类。最终代码如下:

#include <string>

template class std::basic_string<char>;

int main()
{
    std::string::size_type (std::string::*function)() const = &std::string::size;
    return 0;
}

更多信息在这里:using extern template (C++11)

【讨论】:

  • 使用-O2 或更高版本构建也解决了我的问题,您尝试过吗?
猜你喜欢
  • 2014-04-17
  • 2011-09-27
  • 2022-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-16
相关资源
最近更新 更多