为什么不能在 c++0x 模式下使用 libc++ 链接这个 boost::program_options 示例?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8454329/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:35:41  来源:igfitidea点击:

Why can't clang with libc++ in c++0x mode link this boost::program_options example?

c++boostc++11clanglibc++

提问by x-x

Compiling this example code for boost::program_options: http://svn.boost.org/svn/boost/trunk/libs/program_options/example/first.cpp

为 boost::program_options 编译此示例代码:http: //svn.boost.org/svn/boost/trunk/libs/program_options/example/first.cpp

...on MacOS Lion (10.7.2), using boost-1.48.0 installed with MacPorts:

...在 MacOS Lion (10.7.2) 上,使用安装了 MacPorts 的 boost-1.48.0:

$ clang++ -v
Apple clang version 3.0 (tags/Apple/clang-211.12) (based on LLVM 3.0svn)
Target: x86_64-apple-darwin11.2.0
Thread model: posix
$ clang++ -std=c++0x --stdlib=libc++ -lc++ -I/opt/local/include -L/opt/local/lib -lboost_program_options first.cpp -o first
Undefined symbols for architecture x86_64:
  "boost::program_options::options_description::options_description(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned int, unsigned int)", referenced from:
      _main in cc-6QQcwm.o
  "boost::program_options::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, boost::program_options::options_description const&)", referenced from:
      _main in cc-6QQcwm.o
  "boost::program_options::abstract_variables_map::operator[](std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const", referenced from:
      boost::program_options::variables_map::operator[](std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const in cc-6QQcwm.o
  "boost::program_options::detail::cmdline::set_additional_parser(boost::function1<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>)", referenced from:
      boost::program_options::basic_command_line_parser<char>::extra_parser(boost::function1<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>) in cc-6QQcwm.o
  "boost::program_options::detail::cmdline::cmdline(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&)", referenced from:
      boost::program_options::basic_command_line_parser<char>::basic_command_line_parser(int, char const* const*) in cc-6QQcwm.o
  "boost::program_options::to_internal(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
      std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > boost::program_options::to_internal<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) in cc-6QQcwm.o
  "boost::program_options::invalid_option_value::invalid_option_value(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
      void boost::program_options::validate<int, char>(boost::any&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, int*, long) in cc-6QQcwm.o
  "boost::program_options::validation_error::validation_error(boost::program_options::validation_error::kind_t, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
      std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const& boost::program_options::validators::get_single_string<char>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, bool) in cc-6QQcwm.o
  "boost::program_options::value_semantic_codecvt_helper<char>::parse(boost::any&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, bool) const", referenced from:
      vtable for boost::program_options::typed_value<int, char> in cc-6QQcwm.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

The same code compiled/linked with g++4.7 installed with MacPorts:

使用 MacPorts 安装的 g++4.7 编译/链接的相同代码:

$ g++-mp-4.7 -std=c++0x -I/opt/local/include -L/opt/local/lib -lboost_program_options -o first first.cpp

... works fine. As does using clang without libc++:

... 工作正常。与在没有 libc++ 的情况下使用 clang 一样:

clang++ -std=c++0x -I/opt/local/include -L/opt/local/lib -lboost_program_options first.cpp -o first

What's wrong? Why does boost::program_options and libc++ not work together?

怎么了?为什么 boost::program_options 和 libc++ 不能一起工作?

回答by Howard Hinnant

You need to rebuild boost using clang++ -stdlib=libc++.

您需要使用 clang++ -stdlib=libc++ 重建 boost。

libc++ is not binary compatible with gcc's libstdc++ (except for some low level stuff such as operator new). For example the std::stringin gcc's libstdc++ is refcounted, whereas in libc++ it uses the "short string optimization". If you were to accidentally mix these two strings in the same program (and mistake them for the same data structure), you would inevitably get a run time crash.

libc++ 与 gcc 的 libstdc++ 不是二进制兼容的(除了一些低级的东西,比如 operator new)。例如,std::string在 gcc 的 libstdc++ 中被引用计数,而在 libc++ 中它使用“短字符串优化”。如果您不小心在同一个程序中混合了这两个字符串(并将它们误认为是相同的数据结构),您将不可避免地遇到运行时崩溃。

This accident is exactly what has occurred in your case.

这起事故正是在你的情况下发生的。

In order to turn this run time crash into a link time error, libc++ uses a C++11 language feature called inline namespaceto change the ABIof std::stringwithout impacting the APIof std::string. That is, to you std::stringlooks the same. But to the linker, std::stringis being mangled as if it is in namespace std::__1. Thus the linker knows that std::basic_stringand std::__1::basic_stringare two different data structures (the former coming from gcc's libstdc++ and the latter coming from libc++).

为了把这个运行时撞向一个链接时错误的libc ++采用了C ++名为11的语言功能inline namespace改变ABIstd::string不影响APIstd::string。也就是说,在你std::string看来是一样的。但是对于链接器来说,std::string就像在 namespace 中一样被破坏了std::__1。因此,链接器知道std::basic_stringstd::__1::basic_string是两种不同的数据结构(前者来自 gcc 的 libstdc++,后者来自 libc++)。