ThreadSanitizer gives me an alleged race condition in boost::regex_match. Is this a false positive? I cannot find synchronization primitives that depend on BOOST_HAS_THREADS in the callstacks. All input parameters are on the stack of the respective thread and not shared.
==================
WARNING: ThreadSanitizer: data race (pid=1893)
Write of size 4 at 0x007e19fa8ff0 by thread T36:
#0 boost::re_detail_106700::saved_state::saved_state(unsigned int) include/boost/regex/v4/perl_matcher_non_recursive.hpp:59
#1 boost::re_detail_106700::perl_matcher<char const*, std::allocator<boost::sub_match<char const*> >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::push_recursion_stopper() include/boost/regex/v4/perl_matcher_non_recursive.hpp:288
#2 boost::re_detail_106700::perl_matcher<char const*, std::allocator<boost::sub_match<char const*> >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::match_all_states() include/boost/regex/v4/perl_matcher_non_recursive.hpp:202
#3 boost::re_detail_106700::perl_matcher<char const*, std::allocator<boost::sub_match<char const*> >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::match_prefix() include/boost/regex/v4/perl_matcher_common.hpp:336
#4 boost::re_detail_106700::perl_matcher<char const*, std::allocator<boost::sub_match<char const*> >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::match_imp() include/boost/regex/v4/perl_matcher_common.hpp:220
#5 boost::re_detail_106700::perl_matcher<char const*, std::allocator<boost::sub_match<char const*> >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::match() include/boost/regex/v4/perl_matcher_common.hpp:193
#6 bool boost::regex_match<char const*, std::allocator<boost::sub_match<char const*> >, char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >(char const*, char const*, boost::match_results<char const*, std::allocator<boost::sub_match<char const*> > >&, boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > const&, boost::regex_constants::_match_flags) include/boost/regex/v4/regex_match.hpp:50
#7 bool boost::regex_match<char, std::allocator<boost::sub_match<char const*> >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >(char const*, boost::match_results<char const*, std::allocator<boost::sub_match<char const*> > >&, boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > const&, boost::regex_constants::_match_flags) /var/lib/jenkins/workspace/nightly-jnd-navigation__tsd-nav-rsi-viwi-dev/system/ext-boost-dev/dist/17-89ad-bc06/usr/include/boost/regex/v4/regex_match.hpp:73 (tsd.nav.mainapp.mib3+0x3dd0610)
<...>
Previous write of size 4 at 0x007e19fa8ff0 by thread T105:
[failed to restore the stack]
Location is heap block of size 4096 at 0x007e19fa8000 allocated by thread T105:
#0 operator new(unsigned long) <null> (libtsan.so.0+0x79f54)
#1 boost::re_detail_106700::save_state_init::save_state_init(boost::re_detail_106700::saved_state**, boost::re_detail_106700::saved_state**) include/boost/regex/v4/perl_matcher_non_recursive.hpp:107
#2 boost::re_detail_106700::perl_matcher<char const*, std::allocator<boost::sub_match<char const*> >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::match_imp() include/boost/regex/v4/perl_matcher_common.hpp:202
#3 boost::re_detail_106700::perl_matcher<char const*, std::allocator<boost::sub_match<char const*> >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::match() include/boost/regex/v4/perl_matcher_common.hpp:193
#4 bool boost::regex_match<char const*, std::allocator<boost::sub_match<char const*> >, char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >(char const*, char const*, boost::match_results<char const*, std::allocator<boost::sub_match<char const*> > >&, boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > const&, boost::regex_constants::_match_flags) include/boost/regex/v4/regex_match.hpp:50
#5 bool boost::regex_match<char, std::allocator<boost::sub_match<char const*> >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >(char const*, boost::match_results<char const*, std::allocator<boost::sub_match<char const*> > >&, boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > const&, boost::regex_constants::_match_flags) include/boost/regex/v4/regex_match.hpp:73
<...>
Regards
I think the documentation is pretty definitive:
Thread Safety
The Boost.Regex library is thread safe when Boost is: you can verify
that Boost is in thread safe mode by checking to see if
BOOST_HAS_THREADS is defined: this macro is set automatically by the
config system when threading support is turned on in your compiler.
Class basic_regex and its typedefs regex and wregex are thread safe,
in that compiled regular expressions can safely be shared between
threads. The matching algorithms regex_match, regex_search, and
regex_replace are all re-entrant and thread safe. Class match_results
is now thread safe, in that the results of a match can be safely
copied from one thread to another (for example one thread may find
matches and push match_results instances onto a queue, while another
thread pops them off the other end), otherwise use a separate instance
of match_results per thread.
The POSIX API functions are all re-entrant and thread safe, regular
expressions compiled with regcomp can also be shared between threads.
The class RegEx is only thread safe if each thread gets its own RegEx
instance (apartment threading) - this is a consequence of RegEx
handling both compiling and matching regular expressions.
Finally note that changing the global locale invalidates all compiled
regular expressions, therefore calling set_locale from one thread
while another uses regular expressions will produce unpredictable
results.
There is also a requirement that there is only one thread executing
prior to the start of main().
So, you need to make sure:
you are not sharing the match_results object (your description doesn't say, because that's not an input argument depending on your definition)
the regex is pre-compiled:
[are] thread safe,
in that compiled regular expressions can safely be shared between
threads
Related
I am getting below error while building static library uhd-types and linking with boost libraries v1.74 with memory sanitizer flag -fsanitize=memory.
[ 63%] Built target uhd-types
[ 65%] Linking CXX executable ../../bin/unit_tests
/usr/bin/ld: ../../lib/libuhd-types.a(device_addr.cpp.o): in function `boost::re_detail_107400::cpp_regex_traits_implementation<char>::lookup_collatename(char const*, char const*) const':
/root/include/boost/regex/v4/cpp_regex_traits.hpp:680: undefined reference to `boost::re_detail_107400::lookup_default_collate_name(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)'
/usr/bin/ld: ../../lib/libuhd-types.a(device_addr.cpp.o): in function `boost::re_detail_107400::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::fail(boost::regex_constants::error_type, long, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, long)':
/root/include/boost/regex/v4/basic_regex_parser.hpp:245: undefined reference to `boost::regex_error::regex_error(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, boost::regex_constants::error_type, long)'
/usr/bin/ld: ../../lib/libuhd-types.a(device_addr.cpp.o): in function `boost::re_detail_107400::basic_regex_creator<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::fixup_recursions(boost::re_detail_107400::re_syntax_base*)':
/root/include/boost/regex/v4/basic_regex_creator.hpp:788: undefined reference to `boost::regex_error::regex_error(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, boost::regex_constants::error_type, long)'
/usr/bin/ld: /root//include/boost/regex/v4/basic_regex_creator.hpp:877: undefined reference to `boost::regex_error::regex_error(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, boost::regex_constants::error_type, long)'
/usr/bin/ld: ../../lib/libuhd-types.a(device_addr.cpp.o): in function `boost::re_detail_107400::basic_regex_creator<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::create_startmaps(boost::re_detail_107400::re_syntax_base*)':
/root/include/boost/regex/v4/basic_regex_creator.hpp:943: undefined reference to `boost::regex_error::regex_error(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, boost::regex_constants::error_type, long)'
/usr/bin/ld: ../../lib/libuhd-types.a(device_addr.cpp.o): in function `boost::re_detail_107400::basic_regex_creator<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::create_startmap(boost::re_detail_107400::re_syntax_base*, unsigned char*, unsigned int*, unsigned char)':
/root/include/boost/regex/v4/basic_regex_creator.hpp:1156: undefined reference to `boost::regex_error::regex_error(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, boost::regex_constants::error_type, long)'
clang-10: error: linker command failed with exit code 1 (use -v to see invocation)
I already linking uhd-types to boost libraries using target_link_libraries.
I'm very new with boost spirit (and with boost). Its very interesting library.
I use qtcreator + MinGW 5.3.
I simply add every source file from git_hub_calc8 into new project and add some boost library, but i got the following error trying to build (All other examples work fine)
C:\Program Files\boost\boost\boost\spirit\home\x3\nonterminal\rule.hpp:113: ошибка: undefined reference to `bool client::parser::parse_rule<__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, boost::spirit::x3::context<boost::spirit::x3::error_handler_tag, std::reference_wrapper<boost::spirit::x3::error_handler<__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, boost::spirit::x3::context<boost::spirit::x3::skipper_tag, boost::spirit::x3::char_class<boost::spirit::char_encoding::ascii, boost::spirit::x3::space_tag> const, boost::spirit::x3::unused_type> >, std::__cxx11::list<client::ast::statement, std::allocator<client::ast::statement> > >(boost::spirit::x3::rule<client::parser::statement_class, std::__cxx11::list<client::ast::statement, std::allocator<client::ast::statement> >, false>, __gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, __gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, boost::spirit::x3::context<boost::spirit::x3::error_handler_tag, std::reference_wrapper<boost::spirit::x3::error_handler<__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, boost::spirit::x3::context<boost::spirit::x3::skipper_tag, boost::spirit::x3::char_class<boost::spirit::char_encoding::ascii, boost::spirit::x3::space_tag> const, boost::spirit::x3::unused_type> > const&, std::__cxx11::list<client::ast::statement, std::allocator<client::ast::statement> >&)'
What did i wrong? How should i create project with this example?
Seems like a problem with BOOST_SPIRIT_DECLARE beacause a place pointed out by error is call for a template function connected with this define
(template <typename Iterator, typename Context, typename Attribute_>
bool parse(Iterator& first, Iterator const& last
, Context const& context, unused_type, Attribute_& attr) const
{
return parse_rule(*this, first, last, context, attr);
}
The BOOST_SPIRIT_INSTANTIATE marco is equivalent to doing
namespace client { namespace parser
{
template bool parse_rule<iterator_type, context_type, statement_type::attribute_type>(
statement_type rule_, iterator_type &first, iterator_type const &last,
context_type const &context,
statement_type ::attribute_type &attr);
;
}}
So the crucial bit is that iterator_type and context_type match exactly the ones required at the call site. Now, the unresolved symbol is (demangled):
bool client::parser::parse_rule<
__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >,
boost::spirit::x3::context<
boost::spirit::x3::error_handler_tag,
std::reference_wrapper<boost::spirit::x3::error_handler<__gnu_cxx::__normal_iterator<
char const *, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >,
boost::spirit::x3::context<
boost::spirit::x3::skipper_tag,
boost::spirit::x3::char_class<boost::spirit::char_encoding::ascii, boost::spirit::x3::space_tag> const,
boost::spirit::x3::unused_type> >,
std::__cxx11::list<client::ast::statement, std::allocator<client::ast::statement> >
>
(boost::spirit::x3::rule<client::parser::statement_class, std::__cxx11::list<client::ast::statement, std::allocator<client::ast::statement> >, false>,
__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&,
__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&,
boost::spirit::x3::context<
boost::spirit::x3::error_handler_tag,
std::reference_wrapper<boost::spirit::x3::error_handler<__gnu_cxx::__normal_iterator<
char const *, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >,
boost::spirit::x3::context<
boost::spirit::x3::skipper_tag,
boost::spirit::x3::char_class<boost::spirit::char_encoding::ascii, boost::spirit::x3::space_tag> const,
boost::spirit::x3::unused_type> > const &,
std::__cxx11::list<client::ast::statement, std::allocator<client::ast::statement> >&)
This implies the iterator_type should be:
__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >,
Which is indeed what std::string::const_iterator expands to on my system. So, the mismatch is likely in the context type. By adding a forced type error above the BOOST_SPIRIT_INSTANTIATE invocation like so:
struct {} _ = *static_cast<client::parser::context_type*>(nullptr);
I was able to force the compiler to output the expanded type of context_type at the point of instantiation:
statement.cpp:12 error: conversion from ‘client::parser::context_type {aka boost::spirit::x3::context<boost::spirit::x3::error_handler_tag, const std::reference_wrapper<boost::spirit::x3::error_handler<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > > >, boost::spirit::x3::context<boost::spirit::x3::skipper_tag, const boost::spirit::x3::char_class<boost::spirit::char_encoding::ascii, boost::spirit::x3::space_tag>, boost::spirit::x3::unused_type> >}’ to non-scalar type ‘client::parser::<anonymous struct>’ requested
Which tells us the context type is (formatted for legibility):
boost::spirit::x3::context<
boost::spirit::x3::error_handler_tag,
const std::reference_wrapper<boost::spirit::x3::error_handler<
__gnu_cxx::__normal_iterator<const char *, std::__cxx11::basic_string<char> > > >,
boost::spirit::x3::context<
boost::spirit::x3::skipper_tag,
boost::spirit::x3::char_class<boost::spirit::char_encoding::ascii, boost::spirit::x3::space_tag> const,
boost::spirit::x3::unused_type> >,
BUT: the linker has it as
boost::spirit::x3::context<
boost::spirit::x3::error_handler_tag,
std::reference_wrapper<boost::spirit::x3::error_handler<
__gnu_cxx::__normal_iterator<const char *, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >,
boost::spirit::x3::context<
boost::spirit::x3::skipper_tag,
boost::spirit::x3::char_class<boost::spirit::char_encoding::ascii, boost::spirit::x3::space_tag> const,
boost::spirit::x3::unused_type> >
The most conspicuous difference is in the spelling of the defaulted template arguments on std::basic_string (char_traits and the allocator), but that's not actually a difference. The difference that DOES matter, though, is the absense of const with the reference_wrapper<> type.
Fixing It
I suppose this might have been a change once upon a time in the history of X3. The easiest fix in this case is to drop the const in config.hpp:
typedef x3::context<
error_handler_tag
, std::reference_wrapper<error_handler_type>
, phrase_context_type>
context_type;
And indeed, it now compiles
After I fixed some weird HD problems at my server I noticed that all the rethinkdb data had been lost, that wasn't a problem because the data wasn't important, but now when I start the rethinkdb service using sudo /etc/init.d/rethinkdb restart it runs into this error:
2017-06-19T00:58:21.734419185 0.174516s notice: Running rethinkdb 2.3.5~0xenial (GCC 5.3.1)...
2017-06-19T00:58:21.783052748 0.223140s notice: Running on Linux 4.4.0-79-generic i686
2017-06-19T00:58:21.783317738 0.223398s notice: Loading data from directory /var/lib/rethinkdb/instance1/data
2017-06-19T00:58:22.008209401 0.448290s info: Automatically using cache size of 100 MB
2017-06-19T00:58:22.009815969 0.449896s warn: Cache size does not leave much memory for server and query overhead (available memory: 877 MB).
2017-06-19T00:58:22.010366140 0.450446s warn: Cache size is very low and may impact performance.
2017-06-19T00:58:22.042696622 0.482776s notice: Listening for intracluster connections on port 29015
2017-06-19T00:58:22.128827940 0.568909s error: Error in src/btree/reql_specific.cc at line 256:
2017-06-19T00:58:22.129000921 0.569083s error: Unrecognized reql_btree_superblock_t::magic found.
2017-06-19T00:58:22.129123530 0.569204s error: Backtrace:
2017-06-19T00:58:22.703288073 1.143377s error: Mon Jun 19 00:58:22 2017\n\n1 [0x8747198]: backtrace_t::backtrace_t() at ??:?\n2 [0x8747678]: format_backtrace[abi:cxx11](bool) at ??:?\n3 [0x8a208f4]: report_fatal_error(char const*, int, char const*, ...) at ??:?\n4 [0x86deb12]: get_superblock_metainfo(real_superblock_t*, std::vector<std::pair<std::vector<char, std::allocator<char> >, std::vector<char, std::allocator<char> > >, std::allocator<std::pair<std::vector<char, std::allocator<char> >, std::vector<char, std::allocator<char> > > > >*, cluster_version_t*) at ??:?\n5 [0x85df957]: store_metainfo_manager_t::store_metainfo_manager_t(real_superblock_t*) at ??:?\n6 [0x846edc9]: store_t::store_t(hash_region_t<key_range_t> const&, serializer_t*, cache_balancer_t*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool, perfmon_collection_t*, rdb_context_t*, io_backender_t*, base_path_t const&, uuid_u, update_sindexes_t) at ??:?\n7 [0x894745b]: real_multistore_ptr_t::real_multistore_ptr_t(uuid_u const&, serializer_filepath_t const&, scoped_ptr_t<real_branch_history_manager_t>&&, base_path_t const&, io_backender_t*, cache_balancer_t*, rdb_context_t*, perfmon_collection_t*, scoped_ptr_t<thread_allocation_t>&&, std::vector<scoped_ptr_t<thread_allocation_t>, std::allocator<scoped_ptr_t<thread_allocation_t> > >&&, std::map<uuid_u, std::pair<real_multistore_ptr_t*, auto_drainer_t::lock_t>, std::less<uuid_u>, std::allocator<std::pair<uuid_u const, std::pair<real_multistore_ptr_t*, auto_drainer_t::lock_t> > > >*)::{lambda(int)#1}::operator()(int) const at ??:?\n8 [0x89487d4]: callable_action_instance_t<pmap_runner_one_arg_t<real_multistore_ptr_t::real_multistore_ptr_t(uuid_u const&, serializer_filepath_t const&, scoped_ptr_t<real_branch_history_manager_t>&&, base_path_t const&, io_backender_t*, cache_balancer_t*, rdb_context_t*, perfmon_collection_t*, scoped_ptr_t<thread_allocation_t>&&, std::vector<scoped_ptr_t<thread_allocation_t>, std::allocator<scoped_ptr_t<thread_allocation_t> > >&&, std::map<uuid_u, std::pair<real_multistore_ptr_t*, auto_drainer_t::lock_t>, std::less<uuid_u>, std::allocator<std::pair<uuid_u const, std::pair<real_multistore_ptr_t*, auto_drainer_t::lock_t> > > >*)::{lambda(int)#1}, long long> >::run_action() at ??:?\n9 [0x864f4bd]: coro_t::run() at ??:?
2017-06-19T00:58:22.703737641 1.143820s error: Exiting.
Also, it works if I start it using the normal command (rethinkdb --bind all), the error only happens with the proccess.
Trying to compile this cfgparser example.
$ g++ example.cc -lcfgparser
: In function `main':
example.cc:(.text+0x6b): undefined reference to `ConfigParser_t::readFile(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
example.cc:(.text+0x160): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) const'
example.cc:(.text+0x2d9): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int*) const'
example.cc:(.text+0x43c): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, double*) const'
example.cc:(.text+0x5b1): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool*) const'
example.cc:(.text+0x78c): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >*) const'
example.cc:(.text+0xa15): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) const'
example.cc:(.text+0xba2): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) const'
example.cc:(.text+0xd15): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) const'
example.cc:(.text+0xe7f): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) const'
collect2: error: ld returned 1 exit statu
But clearly those symbols are there:
$ nm -gC /usr/lib/libcfgparser.so
000000000003710 T ConfigParser_t::readFile(std::string const&)
0000000000004880 T ConfigParser_t::ConfigParser_t(std::string const&)
00000000000024c0 T ConfigParser_t::ConfigParser_t()
0000000000004ad0 T ConfigParser_t::ConfigParser_t(std::string const&)
00000000000024a0 T ConfigParser_t::ConfigParser_t()
0000000000004d20 T ConfigParser_t::getOptions(std::string const&) const
00000000000028d0 T ConfigParser_t::getSections() const
0000000000002ff0 T ConfigParser_t::getValue(std::string, std::string, bool*) const
0000000000002de0 T ConfigParser_t::getValue(std::string, std::string, double*) const
0000000000002bd0 T ConfigParser_t::getValue(std::string, std::string, int*) const
00000000000027d0 T ConfigParser_t::getValue(std::string, std::string, std::string*) const
0000000000003500 T ConfigParser_t::getValue(std::string, std::string, std::vector<std::string, std::allocator<std::string> >*) const
Unlike other similar problems on SO, this is NOT about linking order, as there is only one object file being linked. Anything I'm missing??
But clearly those symbols are there:
Clearly, they're not. Take a closer look and you will see that
there are no matches between the signatures reported by your
linker as undefined and those reported from the library by
nm.
The Standard header <string> defines std::string as typedef for:
std::basic_string<char, std::char_traits<char>, std::allocator<char>>
The GCC implementation of <string>, as of the cxx11 ABI (GCC 4.7.0)
defines std::string as a typedef for:
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>
The std::__cxx11 name space encloses types whose binary implementations are
compliant with the cxx11 ABI.
That type definition means that C++ translation unit that includes the Standard header <string> won't
compile, with GCC >= 4.7, into object code containing a symbol that demangles as std::string.
If a binary - like your libcfgparser.so - contains a symbol that demangles as std::string, then
whatever that symbol might have referred to in the sources from which it was built, it does not refer to std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>,
and cannot be linked with other binaries that were compiled with that definition of std::string.
Your libcfgparser.so is the one installed by libcfgparser0_1.1.2_amd64.deb from the
cfgparser Sourceforce project
(which was last updated three years ago). I guess this from that the fact that I
get your linkage error with same example.cc program linked against the library that is installed by that package.
The explanation for the error is revealed by:
/usr/lib$ strings -a libcfgparser.so | grep "GCC: ("
GCC: (Debian 4.3.2-1.1) 4.3.2
...
which tells us that this library was built with GCC 4.3.2 - pre the cxx11 ABI.
The std::string that appears in your nm output is a pre-cxx11 demangling abbreviation
of std::basic_string<char, std::char_traits<char>, std::allocator<char>>.
This libcfgparser.so is ABI-incompatible with your current GCC, so you
can't link it with programs that you build with that compiler. What you can do is
build libcfgparser from the source package, libcfgparser-1.1.2.tar.bz2,
with your current compiler and then link your programs with the library you have
built yourself.
That works, but not effortlessly. First you'll need to fix the broken
and antiquated autotooling of the source package to create a working ./configure
script.
Which doesn't give a reassuring impression of the proficiency of the package maintainer.
Plus the source code of the package, copyright 2008, is of amateur quality. If
what you are after is a C++ parser for INI-style files, then boost::property_tree::ini_parser would be the
goto solution. See this answer
I'm testing Boost.Python and have run into some issues.
I managed to complete the "Hello World" example without a glitch (http://www.boost.org/doc/libs/1_54_0/libs/python/doc/tutorial/doc/html/index.html) - everything compiled and I was able to use the .so properly in Python.
However, as soon as I introduced classes into my test file (http://www.boost.org/doc/libs/1_54_0/libs/python/doc/tutorial/doc/html/python/exposing.html), the compiler started screaming
Undefined symbols for architecture x86_64:
"boost::python::objects::function_object(boost::python::objects::py_function const&, std::__1::pair<boost::python::detail::keyword const*, boost::python::detail::keyword const*> const&)", referenced from:
boost::python::api::object boost::python::detail::make_function_aux<void (World::*)(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >), boost::python::default_call_policies, boost::mpl::vector3<void, World&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, mpl_::int_<0> >(void (World::*)(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >), boost::python::default_call_policies const&, boost::mpl::vector3<void, World&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, std::__1::pair<boost::python::detail::keyword const*, boost::python::detail::keyword const*> const&, mpl_::int_<0>) in SHLibPy.o
boost::python::api::object boost::python::detail::make_function_aux<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > (World::*)(), boost::python::default_call_policies, boost::mpl::vector2<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, World&>, mpl_::int_<0> >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > (World::*)(), boost::python::default_call_policies const&, boost::mpl::vector2<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, World&> const&, std::__1::pair<boost::python::detail::keyword const*, boost::python::detail::keyword const*> const&, mpl_::int_<0>) in SHLibPy.o
boost::python::api::object boost::python::detail::make_function_aux<void (*)(_object*), boost::python::default_call_policies, boost::mpl::vector2<void, _object*>, mpl_::int_<0> >(void (*)(_object*), boost::python::default_call_policies const&, boost::mpl::vector2<void, _object*> const&, std::__1::pair<boost::python::detail::keyword const*, boost::python::detail::keyword const*> const&, mpl_::int_<0>) in SHLibPy.o
"boost::python::objects::register_dynamic_id_aux(boost::python::type_info, std::__1::pair<void*, boost::python::type_info> (*)(void*))", referenced from:
void boost::python::objects::register_dynamic_id<World>(World*) in SHLibPy.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
It seems to suggest that the lib files are not linked, but I've included them in XCode
Am I missing something? Thanks very much!
I found out why. Turns out that I'm using the standard library with C++11 support. To fix the issue, I rebuilt boost using brew as follows
brew -v install --with-icu --build-from-source --with-c++11 boost