使用指向成员 std::string::size 的指针无法使用 libc++ link 但可以使用 libstdc++
Taking pointer to member std::string::size fails to link with libc++ but works with libstdc++
我正在做一个需要使用 libc++ 的项目。我遇到了以下问题:
当我尝试编译以下代码时:
#include <string>
int main()
{
std::string::size_type (std::string::*function)() const = &std::string::size;
return 0;
}
我收到以下错误:
ld: symbol(s) not found for architecture 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)
这看起来像是此线程的 libc++
错误:_LIBCPP_INLINE_VISIBILITY and std::string::length 它在做类似的事情,Howard Hinnant 的回应是:
I believe this is due to a poor interaction in the compiler between
extern templates and __attribute__ ((__always_inline__)). If
std::string is not declared extern template, then the compiler will
outline a size() member and you won't get this link error.
In my opinion, clang should not assume that extern templates have
definitions for inlined members, especially those marked
always_inline, and the fact that it does is a clang bug resulting in
the link error you see.
The rationale for the use of always_inline in libc++ is to control the
ABI of libc++. In the past I have watched compilers use different
heuristics from release to release on making the inline/outline
decision. This can cause code to be silently added to and removed
from a dylib. With the use of always_inline, I am telling the
compiler to never add that code to the libc++.dylib binary.
Each of the macros defined and used by libc++ can be overridden.
_LIBCPP_INLINE_VISIBILITY controls how an inlined function is attributed and defaults to:
#ifndef _LIBCPP_INLINE_VISIBILITY
#define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__visibility__("hidden"), __always_inline__))
#endif
You can turn this off with:
-D_LIBCPP_INLINE_VISIBILITY=""
And extern templates are done with:
#ifndef _LIBCPP_EXTERN_TEMPLATE
#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
#endif
This latter one is more difficult to "turn off". The incantation is:
-D'_LIBCPP_EXTERN_TEMPLATE(...)='
Using either (or both) of these workarounds will silence your link
error. But a bug report against clang might be a better long term
solution.
我无法在 coliru but I can on wandbox 上重现此问题,使用 -O2
标志的优化可以解决问题。我无法让 wandbox 接受上面建议的 -D
选项,所以不确定它是否有效。
在我的本地机器上,Howard 的解决方案有效:
clang++ -D_LIBCPP_INLINE_VISIBILITY="" -D'_LIBCPP_EXTERN_TEMPLATE(...)='
我还没有找到错误报告,如果找不到,提交一份可能有意义。
在查看 Shafik Yaghmour 信息后,我找到了一个不需要修改编译标志的解决方案。
解决方案是强制编译器实例化外部模板 class。最终代码如下:
#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)
我正在做一个需要使用 libc++ 的项目。我遇到了以下问题:
当我尝试编译以下代码时:
#include <string>
int main()
{
std::string::size_type (std::string::*function)() const = &std::string::size;
return 0;
}
我收到以下错误:
ld: symbol(s) not found for architecture 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)
这看起来像是此线程的 libc++
错误:_LIBCPP_INLINE_VISIBILITY and std::string::length 它在做类似的事情,Howard Hinnant 的回应是:
I believe this is due to a poor interaction in the compiler between extern templates and __attribute__ ((__always_inline__)). If std::string is not declared extern template, then the compiler will outline a size() member and you won't get this link error.
In my opinion, clang should not assume that extern templates have definitions for inlined members, especially those marked always_inline, and the fact that it does is a clang bug resulting in the link error you see.
The rationale for the use of always_inline in libc++ is to control the ABI of libc++. In the past I have watched compilers use different heuristics from release to release on making the inline/outline decision. This can cause code to be silently added to and removed from a dylib. With the use of always_inline, I am telling the compiler to never add that code to the libc++.dylib binary.
Each of the macros defined and used by libc++ can be overridden.
_LIBCPP_INLINE_VISIBILITY controls how an inlined function is attributed and defaults to:
#ifndef _LIBCPP_INLINE_VISIBILITY #define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__visibility__("hidden"), __always_inline__)) #endif
You can turn this off with:
-D_LIBCPP_INLINE_VISIBILITY=""
And extern templates are done with:
#ifndef _LIBCPP_EXTERN_TEMPLATE #define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__; #endif
This latter one is more difficult to "turn off". The incantation is:
-D'_LIBCPP_EXTERN_TEMPLATE(...)='
Using either (or both) of these workarounds will silence your link error. But a bug report against clang might be a better long term solution.
我无法在 coliru but I can on wandbox 上重现此问题,使用 -O2
标志的优化可以解决问题。我无法让 wandbox 接受上面建议的 -D
选项,所以不确定它是否有效。
在我的本地机器上,Howard 的解决方案有效:
clang++ -D_LIBCPP_INLINE_VISIBILITY="" -D'_LIBCPP_EXTERN_TEMPLATE(...)='
我还没有找到错误报告,如果找不到,提交一份可能有意义。
在查看 Shafik Yaghmour 信息后,我找到了一个不需要修改编译标志的解决方案。
解决方案是强制编译器实例化外部模板 class。最终代码如下:
#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)