2011-12-10 32 views
60

Biên soạn này mã ví dụ cho boost :: program_options: http://svn.boost.org/svn/boost/trunk/libs/program_options/example/first.cppTại sao không thể kêu la với libC++ trong c + + chế độ 0x liên kết này tăng :: program_options ví dụ?

... trên hệ điều hành MacOS Lion (10.7.2), sử dụng tăng-1.48.0 cài đặt với MacPorts:

$ 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) 

Cùng mã biên soạn/được liên kết với g ++ 4.7 được cài đặt với MacPorts:

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

... hoạt động tốt. Cũng như sử dụng clang mà không cần libC++:

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

Có vấn đề gì? Tại sao tăng :: program_options và libC++ không hoạt động cùng nhau?

+3

Có vẻ như người liên kết của bạn không thể tìm thấy các libs 64 bit thích hợp. "ld: không tìm thấy (các) biểu tượng cho kiến ​​trúc x86_64" –

Trả lời

129

Bạn cần phải xây dựng lại tăng bằng cách sử dụng clang ++ -stdlib = libC++.

libC++ không tương thích nhị phân với libstdC++ của gcc (ngoại trừ một số công cụ cấp thấp như toán tử mới). Ví dụ: std::string trong libstdC++ của gcc được nạp lại, trong khi trong libC++ nó sử dụng "tối ưu hóa chuỗi ngắn". Nếu bạn vô tình trộn lẫn hai chuỗi này trong cùng một chương trình (và nhầm lẫn chúng với cùng một cấu trúc dữ liệu), bạn chắc chắn sẽ gặp phải một sự cố thời gian chạy.

Tai nạn này chính xác là những gì đã xảy ra trong trường hợp của bạn.

Để biến thời gian chạy tai nạn này vào một thời gian lỗi liên kết, libC++ sử dụng một tính năng ngôn ngữ C++ 11 gọi inline namespace để thay đổi ABI của std::string mà không ảnh hưởng đến API của std::string. Tức là, với bạn, std::string trông giống nhau. Nhưng với trình liên kết, std::string đang bị xáo trộn như thể nó nằm trong không gian tên std::__1. Do đó, mối liên kết biết rằng std::basic_stringstd::__1::basic_string là hai cấu trúc dữ liệu khác nhau (cấu trúc cũ đến từ libstdC++ của gcc và phần tử thứ hai đến từ libC++).

+5

P.S. Làm thế nào để biên dịch lại boost cho clang/libC++: http://stackoverflow.com/questions/8486077/how-to-compile-link-boost-with-clang-libc –

+0

Cảm ơn bạn đã có câu trả lời tuyệt vời! –

+0

Câu hỏi nhanh. Nếu tôi đã làm my_stdlib_str.c_str() sau đó tôi cuối cùng sẽ được đặt lỗi, phải không? Tôi có nghĩa là trong trường hợp đó trên lừa linker sẽ được thông qua? – ShitalShah

Các vấn đề liên quan