为什么不能在C ++ 0x模式下使用libc ++连接这个boost :: program_options例子?

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

…在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) 

使用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 

… 工作正常。 像使用没有libc ++的clang一样:

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

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

你需要使用clang ++ -stdlib = libc ++来重buildboost。

libc ++与gcc的libstdc ++不是二进制兼容的(除了一些低级的东西,比如operator new)。 例如,gcc的libstdc ++中的std::string被refcounted,而在libc ++中则使用“short string optimization”。 如果你不小心在同一个程序中混合使用这两个string(并且将它们误认为是相同的数据结构),那么你将不可避免地导致运行时崩溃。

这个事故就是你的情况。

为了将此运行时崩溃转化为链接时间错误,libc ++使用名为inline namespace的C ++ 11语言特性来更改std::stringABI ,而不会影响std::stringAPI 。 也就是说,你std::string看起来是一样的。 但是对于连接器来说, std::string正在被破坏,就好像它在名字空间std::__1 。 因此,链接器知道std::basic_stringstd::__1::basic_string是两个不同的数据结构(前者来自gcc的libstdc ++,后者来自libc ++)。