将指针指向成员std :: string :: size无法与libc ++链接,但与libstdc ++一起使用

时间:2015-03-29 01:23:15

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

我正在进行一个需要使用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)

2 个答案:

答案 0 :(得分:2)

这看起来像这个帖子的libc++错误:_LIBCPP_INLINE_VISIBILITY and std::string::length 做了类似的事情,Howard Hinnant的回答是:

  

我认为这是由于编译器之间的交互不良造成的   extern模板和__attribute __((__ round_inline__))。如果   std :: string没有声明extern模板,那么编译器就会   概述一个size()成员,你不会得到这个链接错误。

     

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

     

在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 = “”

     

extern模板完成:

#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(...)='

我没有找到错误报告,如果我找不到报告错误报告可能有意义。

答案 1 :(得分:0)

在查看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)