C++ Boost read_json crash and I had #define BOOST_SPIRIT_THREADSAFE - c++

Recently other people upgraded our boost library, now I see this coredump when a read_json function is called heavily. Never seen this before. And I have #define BOOST_SPIRIT_THREADSAFE in the code, that's why this didn't happen before. Really need help!Thanks!
Program terminated with signal 11, Segmentation fault.
#0 0x00007f062ce0d094 in std::mem_fun1_t<int, boost::spirit::classic::impl::grammar_helper_base<boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> > >, boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> >*>::operator() (this=0x7f06120f4c90, __p=0x7f05f813faa0, __x=0x7f06120f4df0) at /usr/lib/gcc/x86_64-spcdn-linux-gnu/4.5.2/../../../../include/c++/4.5.2/bits/stl_function.h:605
in /usr/lib/gcc/x86_64-spcdn-linux-gnu/4.5.2/../../../../include/c++/4.5.2/bits/stl_function.h
#0 0x00007f062ce0d094 in std::mem_fun1_t<int, boost::spirit::classic::impl::grammar_helper_base<boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> > >, boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> >*>::operator() (this=0x7f06120f4c90, __p=0x7f05f813faa0, __x=0x7f06120f4df0) at /usr/lib/gcc/x86_64-spcdn-linux-gnu/4.5.2/../../../../include/c++/4.5.2/bits/stl_function.h:605
#1 0x00007f062ce0c66e in std::binder2nd<std::mem_fun1_t<int, boost::spirit::classic::impl::grammar_helper_base<boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> > >, boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> >*> >::operator() (this=0x7f06120f4c90, __x=#0x7f06001446e0) at /usr/lib/gcc/x86_64-spcdn-linux-gnu/4.5.2/../../../../include/c++/4.5.2/backward/binders.h:154
#2 0x00007f062ce0b87e in std::for_each<std::reverse_iterator<__gnu_cxx::__normal_iterator<boost::spirit::classic::impl::grammar_helper_base<boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> > >**, std::vector<boost::spirit::classic::impl::grammar_helper_base<boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> > >*, std::allocator<boost::spirit::classic::impl::grammar_helper_base<boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> > >*> > > >, std::binder2nd<std::mem_fun1_t<int, boost::spirit::classic::impl::grammar_helper_base<boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> > >, boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> >*> > > (__first=..., __last=..., __f=...) at /usr/lib/gcc/x86_64-spcdn-linux-gnu/4.5.2/../../../../include/c++/4.5.2/bits/stl_algo.h:4185
#3 0x00007f062ce0aa88 in boost::spirit::classic::impl::grammar_destruct<boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> > > (self=0x7f06120f4df0) at /usr/include/boost/spirit/home/classic/core/non_terminal/impl/grammar.ipp:324
#4 0x00007f062ce09c5f in boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> >::~grammar (this=0x7f06120f4df0, __in_chrg=<optimized out>) at /usr/include/boost/spirit/home/classic/core/non_terminal/grammar.hpp:52
#5 0x00007f062ce093f7 in boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::~json_grammar (this=0x7f06120f4df0, __in_chrg=<optimized out>) at /usr/include/boost/property_tree/detail/json_parser_read.hpp:162
#6 0x00007f062ce0987f in boost::property_tree::json_parser::read_json_internal<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > > (stream=..., pt=..., filename="") at /usr/include/boost/property_tree/detail/json_parser_read.hpp:310
#7 0x00007f062ce08eb6 in boost::property_tree::json_parser::read_json<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > > (stream=..., pt=...) at /usr/include/boost/property_tree/json_parser.hpp:45

Everywhere you include json_parser.hpp or Spirit, BOOST_SPIRIT_THREADSAFE must be defined. Defining it globally would be safest, in case another part of boost/yourApp uses Spirit without your knowledge.
For any inclusion where this isn't defined, Sprit annoyingly makes a static variable in grammar.ipp that'll be shared amongst all instances of Spirit. Your grammar_destruct error is because Spirit is missing this define in one of your modules.

Related

Race condition in tbb::concurrent_queue

I am having a data race problem on tbb::concurrent_queue. Here is the code, producer and consumer functions are running on separate threads:
tbb::concurrent_queue<std::string> valid_json_queue;
Consumer:
...
std::string valid_json;
while(1) {
while(valid_json_queue.try_pop(valid_json)) {
json_manager_.parseJson(valid_json);
}
json_manager_.persist();
std::this_thread::sleep_for(std::chrono::seconds(5));
}
...
Producer:
...read data from socket via boost async_read_some...
for(const auto& valid_json : valid_jsons) {
valid_json_queue.push(valid_json);
}
...
I have ran the code with -fsanitizer=thread. Here is the relevant part from the output:
WARNING: ThreadSanitizer: data race (pid=21801)
...
WARNING: ThreadSanitizer: data race (pid=21801)
Write of size 8 at 0x7f861e405c00 by main thread:
#0 tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page::padded_page() /usr/local/include/oneapi/tbb/detail/_concurrent_queue_base.h:80 (dropcopy_mysql_adapter+0x4b77c1)
#1 decltype (::new ((void*)(0)) tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page()) std::construct_at<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page>(tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page*) /usr/local/include/c++/10.1.0/bits/stl_construct.h:97 (dropcopy_mysql_adapter+0x4b6c76)
#2 std::enable_if<std::__and_<std::__and_<std::__not_<std::allocator_traits<tbb::detail::d1::cache_aligned_allocator<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page> >::__construct_helper<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page>::type>, std::is_constructible<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page> > >::value, void>::type std::allocator_traits<tbb::detail::d1::cache_aligned_allocator<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page> >::_S_construct<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page>(tbb::detail::d1::cache_aligned_allocator<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page>&, tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page*) /usr/local/include/c++/10.1.0/bits/alloc_traits.h:259 (dropcopy_mysql_adapter+0x4b6cac)
#3 decltype (_S_construct({parm#1}, {parm#2})) std::allocator_traits<tbb::detail::d1::cache_aligned_allocator<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page> >::construct<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page>(tbb::detail::d1::cache_aligned_allocator<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page>&, tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page*) /usr/local/include/c++/10.1.0/bits/alloc_traits.h:360 (dropcopy_mysql_adapter+0x4b5ab3)
#4 tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::prepare_page(unsigned long, tbb::detail::d2::concurrent_queue_rep<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, tbb::detail::d1::cache_aligned_allocator<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page>, tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page*&) /usr/local/include/oneapi/tbb/detail/_concurrent_queue_base.h:123 (dropcopy_mysql_adapter+0x4b4466)
#5 void tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::push<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(unsigned long, tbb::detail::d2::concurrent_queue_rep<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, tbb::detail::d1::cache_aligned_allocator<tbb::detail::d2::concurrent_queue_rep<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<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&) /usr/local/include/oneapi/tbb/detail/_concurrent_queue_base.h:149 (dropcopy_mysql_adapter+0x4b3123)
#6 void tbb::detail::d2::concurrent_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::internal_push<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/local/include/oneapi/tbb/concurrent_queue.h:177 (dropcopy_mysql_adapter+0x4b1b71)
#7 tbb::detail::d2::concurrent_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::push(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/local/include/oneapi/tbb/concurrent_queue.h:119 (dropcopy_mysql_adapter+0x4b0447)
#8 operator() /home/zhft_003/aydin_space/tools-dropcopy_mysql_adapter/client.cpp:81 (dropcopy_mysql_adapter+0x49e351)
#9 operator() /usr/local/include/boost/asio/detail/bind_handler.hpp:182 (dropcopy_mysql_adapter+0x4a3318)
#10 asio_handler_invoke<boost::asio::detail::binder2<Client::do_read()::<lambda(boost::system::error_code, size_t)>, boost::system::error_code, long unsigned int> > /usr/local/include/boost/asio/handler_invoke_hook.hpp:88 (dropcopy_mysql_adapter+0x4a2be0)
#11 invoke<boost::asio::detail::binder2<Client::do_read()::<lambda(boost::system::error_code, size_t)>, boost::system::error_code, long unsigned int>, Client::do_read()::<lambda(boost::system::error_code, size_t)> > /usr/local/include/boost/asio/detail/handler_invoke_helpers.hpp:54 (dropcopy_mysql_adapter+0x4a26ca)
#12 complete<boost::asio::detail::binder2<Client::do_read()::<lambda(boost::system::error_code, size_t)>, boost::system::error_code, long unsigned int> > /usr/local/include/boost/asio/detail/handler_work.hpp:501 (dropcopy_mysql_adapter+0x4a20d0)
#13 do_complete /usr/local/include/boost/asio/detail/reactive_socket_recv_op.hpp:145 (dropcopy_mysql_adapter+0x4a1447)
#14 boost::asio::detail::scheduler_operation::complete(void*, boost::system::error_code const&, unsigned long) /usr/local/include/boost/asio/detail/scheduler_operation.hpp:40 (dropcopy_mysql_adapter+0x41040a)
#15 boost::asio::detail::epoll_reactor::descriptor_state::do_complete(void*, boost::asio::detail::scheduler_operation*, boost::system::error_code const&, unsigned long) /usr/local/include/boost/asio/detail/impl/epoll_reactor.ipp:776 (dropcopy_mysql_adapter+0x4aae53)
#16 boost::asio::detail::scheduler_operation::complete(void*, boost::system::error_code const&, unsigned long) /usr/local/include/boost/asio/detail/scheduler_operation.hpp:40 (dropcopy_mysql_adapter+0x41040a)
#17 boost::asio::detail::scheduler::do_run_one(boost::asio::detail::conditionally_enabled_mutex::scoped_lock&, boost::asio::detail::scheduler_thread_info&, boost::system::error_code const&) /usr/local/include/boost/asio/detail/impl/scheduler.ipp:486 (dropcopy_mysql_adapter+0x413afc)
#18 boost::asio::detail::scheduler::run(boost::system::error_code&) /usr/local/include/boost/asio/detail/impl/scheduler.ipp:204 (dropcopy_mysql_adapter+0x413511)
#19 boost::asio::io_context::run() <null> (dropcopy_mysql_adapter+0x414000)
#20 main /home/zhft_003/aydin_space/tools-dropcopy_mysql_adapter/main.cpp:59 (dropcopy_mysql_adapter+0x40ace6)
Previous read of size 8 at 0x7f861e405c00 by thread T1:
#0 tbb::detail::d2::micro_queue_pop_finalizer<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::padded_page> >::~micro_queue_pop_finalizer() /usr/local/include/oneapi/tbb/detail/_concurrent_queue_base.h:382 (dropcopy_mysql_adapter+0x4b4b6b)
#1 tbb::detail::d2::micro_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::pop(void*, unsigned long, tbb::detail::d2::concurrent_queue_rep<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, tbb::detail::d1::cache_aligned_allocator<tbb::detail::d2::concurrent_queue_rep<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >&) /usr/local/include/oneapi/tbb/detail/_concurrent_queue_base.h:188 (dropcopy_mysql_adapter+0x4b3479)
#2 tbb::detail::d2::concurrent_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::internal_try_pop(void*) /usr/local/include/oneapi/tbb/concurrent_queue.h:193 (dropcopy_mysql_adapter+0x4b1f26)
#3 tbb::detail::d2::concurrent_queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, tbb::detail::d1::cache_aligned_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::try_pop(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&) /usr/local/include/oneapi/tbb/concurrent_queue.h:135 (dropcopy_mysql_adapter+0x4b0629)
#4 Client::jsonParseLoop() /home/zhft_003/aydin_space/tools-dropcopy_mysql_adapter/client.cpp:124 (dropcopy_mysql_adapter+0x49e875)
#5 void std::__invoke_impl<void, void (Client::*)(), Client*>(std::__invoke_memfun_deref, void (Client::*&&)(), Client*&&) /usr/local/include/c++/10.1.0/bits/invoke.h:73 (dropcopy_mysql_adapter+0x4b941e)
#6 std::__invoke_result<void (Client::*)(), Client*>::type std::__invoke<void (Client::*)(), Client*>(void (Client::*&&)(), Client*&&) /usr/local/include/c++/10.1.0/bits/invoke.h:95 (dropcopy_mysql_adapter+0x4b92e2)
#7 void std::thread::_Invoker<std::tuple<void (Client::*)(), Client*> >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) /usr/local/include/c++/10.1.0/thread:264 (dropcopy_mysql_adapter+0x4b91f2)
#8 std::thread::_Invoker<std::tuple<void (Client::*)(), Client*> >::operator()() /usr/local/include/c++/10.1.0/thread:271 (dropcopy_mysql_adapter+0x4b9182)
#9 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (Client::*)(), Client*> > >::_M_run() /usr/local/include/c++/10.1.0/thread:215 (dropcopy_mysql_adapter+0x4b910c)
#10 execute_native_thread_routine ../../../.././libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcdd5f)
Thread T1 (tid=21803, running) created by main thread at:
#0 pthread_create ../../.././libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x58b22)
#1 __gthread_create /home/zhft_003/downloads/gcc/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/gthr-default.h:663 (libstdc++.so.6+0xcdfd4)
#2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) ../../../.././libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcdfd4)
#3 std::thread std::jthread::_S_create<void (Client::*)(), Client*>(std::stop_source&, void (Client::*&&)(), Client*&&) /usr/local/include/c++/10.1.0/thread:557 (dropcopy_mysql_adapter+0x4b1852)
#4 std::jthread::jthread<void (Client::*)(), Client*, void>(void (Client::*&&)(), Client*&&) /usr/local/include/c++/10.1.0/thread:455 (dropcopy_mysql_adapter+0x4b0031)
#5 Client::Client(boost::asio::io_context&, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> const&) /home/zhft_003/aydin_space/tools-dropcopy_mysql_adapter/client.cpp:18 (dropcopy_mysql_adapter+0x49d8f8)
#6 main /home/zhft_003/aydin_space/tools-dropcopy_mysql_adapter/main.cpp:57 (dropcopy_mysql_adapter+0x40acd7)
client.cpp:124 is the line with while(valid_json_queue.try_pop(valid_json)), whereas client.cpp:81 is the line with valid_json_queue.push(valid_json);.
I thought I was safe using tbb::concurrent_queue in a multithreaded context but apparently I am doing something wrong here.
g++ version is 10.1.0
We observe data races when two or more threads in a single process access the same memory location concurrently.
Concurrent_queue doesn't create any parallelism at all: it just allows multiple threads to safely access the same queue. It ensures there are no race conditions.
We can use a mutex to synchronize the threads and to get rid of data race problems.
Refer to the below links for more details:
https://oneapi-src.github.io/oneTBB/main/tbb_userguide/Concurrent_Queue_Classes.html
https://spec.oneapi.io/versions/latest/elements/oneTBB/source/mutual_exclusion.html
Thanks & Regards,
Noorjahan.

Is an indirect memory leak detected by gcc option -fsanitize=address a concern?

When I test run C++ programs with the option -fsanitize=address I see many locations point to an indirect leak. They are all initiated from libasan.so. The exact error shown below. I am not sure that I am responsible for this leak or not. I was able to fixed other direct leaks in my program.
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x7f24e2b9c947 in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10f947)
#1 0x7f24e2517dc8 in __gnu_cxx::new_allocator<std::pair<char, int> >::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f24e250ed74 in std::allocator_traits<std::allocator<std::pair<char, int> > >::allocate(std::allocator<std::pair<char, int> >&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f24e24ff853 in std::_Vector_base<std::pair<char, int>, std::allocator<std::pair<char, int> > >::_M_allocate(unsigned long) /usr/include/c++/9/bits/stl_vector.h:343
#4 0x7f24e24e8aa6 in std::_Vector_base<std::pair<char, int>, std::allocator<std::pair<char, int> > >::_M_create_storage(unsigned long) /usr/include/c++/9/bits/stl_vector.h:358
#5 0x7f24e24d8ee8 in std::_Vector_base<std::pair<char, int>, std::allocator<std::pair<char, int> > >::_Vector_base(unsigned long, std::allocator<std::pair<char, int> > const&) /usr/include/c++/9/bits/stl_vector.h:302
#6 0x7f24e24c9782 in std::vector<std::pair<char, int>, std::allocator<std::pair<char, int> > >::vector(std::vector<std::pair<char, int>, std::allocator<std::pair<char, int> > > const&) /usr/include/c++/9/bits/stl_vector.h:552
#7 0x7f24e2579da6 in Hitbrief::Hitbrief(Hitbrief const&) /home/kzhou/coding/molbar/src/readcompass.h:21
#8 0x7f24e2579e5b in std::pair<Hitbrief const, int>::pair<Hitbrief&&, 0ul>(std::tuple<Hitbrief&&>&, std::tuple<>&, std::_Index_tuple<0ul>, std::_Index_tuple<>) /usr/include/c++/9/tuple:1674
#9 0x7f24e25798f0 in std::pair<Hitbrief const, int>::pair<Hitbrief&&>(std::piecewise_construct_t, std::tuple<Hitbrief&&>, std::tuple<>) /usr/include/c++/9/tuple:1663
#10 0x7f24e2578f77 in void __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<Hitbrief const, int> > >::construct<std::pair<Hitbrief const, int>, std::piecewise_construct_t const&, std::tuple<Hitbrief&&>, std::tuple<> >(std::pair<Hitbrief const, int>*, std::piecewise_construct_t const&, std::tuple<Hitbrief&&>&&, std::tuple<>&&) /usr/include/c++/9/ext/new_allocator.h:147
#11 0x7f24e2577db5 in void std::allocator_traits<std::allocator<std::_Rb_tree_node<std::pair<Hitbrief const, int> > > >::construct<std::pair<Hitbrief const, int>, std::piecewise_construct_t const&, std::tuple<Hitbrief&&>, std::tuple<> >(std::allocator<std::_Rb_tree_node<std::pair<Hitbrief const, int> > >&, std::pair<Hitbrief const, int>*, std::piecewise_construct_t const&, std::tuple<Hitbrief&&>&&, std::tuple<>&&) /usr/include/c++/9/bits/alloc_traits.h:484
#12 0x7f24e2575199 in void std::_Rb_tree<Hitbrief, std::pair<Hitbrief const, int>, std::_Select1st<std::pair<Hitbrief const, int> >, std::less<Hitbrief>, std::allocator<std::pair<Hitbrief const, int> > >::_M_construct_node<std::piecewise_construct_t const&, std::tuple<Hitbrief&&>, std::tuple<> >(std::_Rb_tree_node<std::pair<Hitbrief const, int> >*, std::piecewise_construct_t const&, std::tuple<Hitbrief&&>&&, std::tuple<>&&) /usr/include/c++/9/bits/stl_tree.h:614
#13 0x7f24e25714e9 in std::_Rb_tree_node<std::pair<Hitbrief const, int> >* std::_Rb_tree<Hitbrief, std::pair<Hitbrief const, int>, std::_Select1st<std::pair<Hitbrief const, int> >, std::less<Hitbrief>, std::allocator<std::pair<Hitbrief const, int> > >::_M_create_node<std::piecewise_construct_t const&, std::tuple<Hitbrief&&>, std::tuple<> >(std::piecewise_construct_t const&, std::tuple<Hitbrief&&>&&, std::tuple<>&&) /usr/include/c++/9/bits/stl_tree.h:631
#14 0x7f24e256e7ae in std::_Rb_tree_iterator<std::pair<Hitbrief const, int> > std::_Rb_tree<Hitbrief, std::pair<Hitbrief const, int>, std::_Select1st<std::pair<Hitbrief const, int> >, std::less<Hitbrief>, std::allocator<std::pair<Hitbrief const, int> > >::_M_emplace_hint_unique<std::piecewise_construct_t const&, std::tuple<Hitbrief&&>, std::tuple<> >(std::_Rb_tree_const_iterator<std::pair<Hitbrief const, int> >, std::piecewise_construct_t const&, std::tuple<Hitbrief&&>&&, std::tuple<>&&) /usr/include/c++/9/bits/stl_tree.h:2455
#15 0x7f24e2568f82 in std::map<Hitbrief, int, std::less<Hitbrief>, std::allocator<std::pair<Hitbrief const, int> > >::operator[](Hitbrief&&) /usr/include/c++/9/bits/stl_map.h:518
Even when all leaks are indirect, there is still memory leak in the source code. I was able to track down all leak and eliminate all indirect leaks. Thank for everyone feedback. In the past, eliminating direct leaks removed all the indirect leaks. This is my first experience, I think it is good to share with someone who experienced this situation for the first time.

Segfault when accessing static map when threading

Consider the following code snippet:
myEnum stringToEnum(const std::string& enumString) {
static const std::unordered_map<std::string, myEnum> conversionMap = {
{"enumA", myEnum::enumA},
{"enumB", myEnum::enumB},
{"enumC", myEnum::enumC}};
if(conversionMap.count(enumString) == 0) {
// Return some default value
}
return conversionMap.at(enumString);
}
void threadedFcn() {
// Do some things
for (int i = 0; i < someNumber; ++i) {
// Do some more things
auto myEnum = stringToEnum(myString);
// Do even more stuff
}
}
int main() {
threadedFcn(); // No problem
std::thread(threadedFcn).join(); // No problem
std::thread(threadedFcn).detach(); // Seg fault
}
A few things about this:
If I remove the call to count then it won't seg fault. It looks like it's caused by that somehow.
It only happens on Linux Debian 9 (I've built with Windows 10 and Mac as well).
If I add something like std::this_thread::sleep_for(std::chrono::milliseconds(2000)); after the detach call, then it won't seg fault.
If I make conversionMap not static, then it won't seg fault.
I can't figure out what the exact problem is, but it's something to do with the main thread exiting before the detached thread finishes.
As Slava correctly said, the problem is that you are letting the main return, while your other thread is running.
Returning from main eventually calls exit, which goes through all registered atexit handlers.
When using libstdc++ (and probably most other C++ runtime implementations), any static C++ object that has been constructed registers its destructor with atexit, so after that destructor fires, your detached thread is accessing destroyed conversionMap object, with predictable results.
You can observe this by using Address Sanitizer (-fsanitize=address), which reports:
=================================================================
==87625==ERROR: AddressSanitizer: heap-use-after-free on address 0x603000000010 at pc 0x563122b9c6c5 bp 0x7fc54eafea20 sp 0x7fc54eafea18
READ of size 8 at 0x603000000010 thread T2
#0 0x563122b9c6c4 in std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> >, std::__detail
::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>
>::_M_bucket_begin(unsigned long) const /usr/include/c++/9/bits/hashtable.h:943
#1 0x563122b9bcf2 in std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> >, std::__detail
::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>
>::count(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const /usr/include/c++/9/bits/hashtable.h:1451
#2 0x563122b9b76e in std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, myEnum, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::ba
sic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> > >::count(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const /usr/include/c++/9/bits/unordered_map.h:939
#3 0x563122b9a793 in stringToEnum(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /tmp/t.cc:16
#4 0x563122b9aa9c in threadedFcn() /tmp/t.cc:27
#5 0x563122b9f71e in void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/9/bits/invoke.h:60
#6 0x563122b9f681 in std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/9/bits/invoke.h:95
#7 0x563122b9f5cb in void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/9/thread:244
#8 0x563122b9f56c in std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/9/thread:251
#9 0x563122b9f4ed in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/9/thread:195
#10 0x7fc552301baf (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xcebaf)
#11 0x7fc55202bf26 in start_thread /build/glibc-M65Gwz/glibc-2.30/nptl/pthread_create.c:479
#12 0x7fc5521532ee in __clone (/lib/x86_64-linux-gnu/libc.so.6+0xfd2ee)
0x603000000010 is located 0 bytes inside of 24-byte region [0x603000000010,0x603000000028)
freed by thread T0 here:
#0 0x7fc552509f97 in operator delete(void*) (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x109f97)
#1 0x563122b9e5fb in __gnu_cxx::new_allocator<std::__detail::_Hash_node_base*>::deallocate(std::__detail::_Hash_node_base**, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x563122b9dbf5 in std::allocator_traits<std::allocator<std::__detail::_Hash_node_base*> >::deallocate(std::allocator<std::__detail::_Hash_node_base*>&, std::__detail::_Hash_node_base**, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x563122b9d0cc in std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum>, true> > >::_M_deallocate_buckets(std::__detail::_Hash_node_base**, unsigned long) /usr/include/c++/9/bits/hashtable_policy.h:2148
#4 0x563122b9c5d3 in std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> >, std::__detail
::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>
>::_M_deallocate_buckets(std::__detail::_Hash_node_base**, unsigned long) /usr/include/c++/9/bits/hashtable.h:370
#5 0x563122b9bc99 in std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> >, std::__detail
::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>
>::_M_deallocate_buckets() /usr/include/c++/9/bits/hashtable.h:375
#6 0x563122b9b73b in std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> >, std::__detail
::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>
>::~_Hashtable() /usr/include/c++/9/bits/hashtable.h:1353
#7 0x563122b9b4ff in std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, myEnum, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::ba
sic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> > >::~unordered_map() /usr/include/c++/9/bits/unordered_map.h:102
#8 0x7fc552093e26 in __run_exit_handlers /build/glibc-M65Gwz/glibc-2.30/stdlib/exit.c:108
previously allocated by thread T0 here:
#0 0x7fc55250919f in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10919f)
#1 0x563122b9e828 in __gnu_cxx::new_allocator<std::__detail::_Hash_node_base*>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x563122b9defc in std::allocator_traits<std::allocator<std::__detail::_Hash_node_base*> >::allocate(std::allocator<std::__detail::_Hash_node_base*>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x563122b9d6d4 in std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum>, true> > >::_M_allocate_buckets(unsigned long) /usr/include/c++/9/bits/hashtable_policy.h:2134
#4 0x563122b9ce5b in std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> >, std::__detail
::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>
>::_M_allocate_buckets(unsigned long) /usr/include/c++/9/bits/hashtable.h:361
#5 0x563122b9c3db in std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> >, std::__detail
::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>
>::_Hashtable<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> const*>(std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> const*, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> const*, unsigned l
ong, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::__detail::_Mod_range_hashing const&, std::__detail::_Default_ranged_hash const&, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::__detail::_Select1st const&, std::allocator<std::pair<std::__cxx
11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> > const&) /usr/include/c++/9/bits/hashtable.h:989
#6 0x563122b9bab5 in std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> >, std::__detail
::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>
>::_Hashtable(std::initializer_list<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&,
std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> > const&) /usr/include/c++/9/bits/hashtable.h:466
#7 0x563122b9b6a3 in std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, myEnum, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::ba
sic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> > >::unordered_map(std::initializer_list<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::equal_to<std::__
cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, myEnum> > const&) /usr/include/c++/9/bits/unordered_map.h:231
#8 0x563122b9a678 in stringToEnum(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /tmp/t.cc:14
#9 0x563122b9aa9c in threadedFcn() /tmp/t.cc:27
#10 0x563122b9ac0f in main /tmp/t.cc:33
#11 0x7fc55207ce0a in __libc_start_main ../csu/libc-start.c:308
Thread T2 created by T0 here:
#0 0x7fc5524399b2 in pthread_create (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x399b2)
#1 0x7fc552301e24 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xcee24)
#2 0x563122b9ac75 in main /tmp/t.cc:35
#3 0x7fc55207ce0a in __libc_start_main ../csu/libc-start.c:308
Update:
I guess an easy fix is to just make my variable not-static (functionally it will be the same but with an obvious performance hit).
There is an easy way to avoid having to construct a new unordered_map on every call, while also avoiding the global destruction problem: use a static pointer:
myEnum stringToEnum(const std::string& enumString) {
static const auto *conversionMap =
new std::unordered_map<std::string, myEnum>{
{"enumA", myEnum::enumA},
{"enumB", myEnum::enumB},
{"enumC", myEnum::enumC}
};
if (conversionMap->count(enumString) == 0) {
// Return some default value
}
return conversionMap->at(enumString);
}

crash in boost::split algorithm (can not access memory)

I am getting following crash in boost algorithm
stack trace is :
#0 0x0000000000451432 in boost::algorithm::predicate_facade<boost::algorithm::detail::is_any_ofF<char>
>::predicate_facade (
this=<error reading variable: Cannot access memory at address 0x7fffff3feff8>) at /med/build/boost/boost_1_43_0/boost/algorithm/string/predicate_facade.hpp:36
#1 0x0000000000451454 in boost::algorithm::detail::is_any_ofF<char>::is_any_ofF (this=0x7fffff3ff090, Other=...)
at /med/build/boost/boost_1_43_0/boost/algorithm/string/detail/classification.hpp:107
#2 0x0000000000452517 in boost::algorithm::detail::token_finderF<boost::algorithm::detail::is_any_ofF<char>
>::operator()<__gnu_cxx::__normal_iterator<char*, std::string> > (
this=0x7ffe5169a6b0, Begin=..., End=...) at /med/build/boost/boost_1_43_0/boost/algorithm/string/detail/finder.hpp:570
#3 0x0000000000453f29 in boost::detail::function::function_obj_invoker2<boost::algorithm::detail::token_finderF<boost::algorithm::detail::is_any_ofF<char>
>, boost::iterator_range<__gnu_cxx::__normal_iterator<char*, std::string> >, __gnu_cxx::__normal_iterator<char*, std::string>,
__gnu_cxx::__normal_iterator<char*, std::string> >::invoke (
function_obj_ptr=..., a0=..., a1=...) at /med/build/boost/boost_1_43_0/boost/function/function_template.hpp:132
#4 0x0000000000453a3a in boost::function2<boost::iterator_range<__gnu_cxx::__normal_iterator<char*, std::string> >, __gnu_cxx::__normal_iterator<char*, std::string>,
__gnu_cxx::__normal_iterator<char*, std::string> >::operator() (this=0x7fffff3ff450, a0=..., a1=...) at /med/build/boost/boost_1_43_0/boost/function/function_template.hpp:1013
#5 0x0000000000453080 in boost::algorithm::detail::find_iterator_base<__gnu_cxx::__normal_iterator<char*, std::string> >::do_find (this=0x7fffff3ff450, Begin=..., End=...)
at /med/build/boost/boost_1_43_0/boost/algorithm/string/detail/find_iterator.hpp:63
#6 0x00000000004527fe in boost::algorithm::split_iterator<__gnu_cxx::__normal_iterator<char*, std::string> >::increment (this=0x7fffff3ff450)
at /med/build/boost/boost_1_43_0/boost/algorithm/string/find_iterator.hpp:297
#7 0x0000000000454f12 in boost::iterator_core_access::increment<boost::algorithm::split_iterator<__gnu_cxx::__normal_iterator<char*, std::string> > > (f=...)
at /med/build/boost/boost_1_43_0/boost/iterator/iterator_facade.hpp:522
#8 0x0000000000454e2c in boost::iterator_facade<boost::algorithm::split_iterator<__gnu_cxx::__normal_iterator<char*, std::string> >, boost::iterator_range<__gnu_cxx::__normal_iterator<char*, std::string>
> const, boost::forward_traversal_tag, boost::iterator_range<__gnu_cxx::__normal_iterator<char*, std::string>
> const&, long>::operator++ (
this=0x7fffff3ff450) at /med/build/boost/boost_1_43_0/boost/iterator/iterator_facade.hpp:664
#9 0x00000000004548a6 in boost::iterator_adaptor<boost::transform_iterator<boost::algorithm::detail::copy_iterator_rangeF<std::string,
__gnu_cxx::__normal_iterator<char*, std::string> >, boost::algorithm::split_iterator<__gnu_cxx::__normal_iterator<char*, std::string> >, boost::use_default, boost::use_default>, boost::algorithm::split_iterator<__gnu_cxx::__normal_iterator<char*, std::string> >, std::string, boost::use_default, std::string, boost::use_default>::increment (this=0x7fffff3ff450)
at /med/build/boost/boost_1_43_0/boost/iterator/iterator_adaptor.hpp:339
#10 0x0000000000454318 in boost::iterator_core_access::increment<boost::transform_iterator<boost::algorithm::detail::copy_iterator_rangeF<std::string,
__gnu_cxx::__normal_iterator<char*, std::string> >, boost::algorithm::split_iterator<__gnu_cxx::__normal_iterator<char*, std::string> >, boost::use_default, boost::use_default> > (f=...)
at /med/build/boost/boost_1_43_0/boost/iterator/iterator_facade.hpp:522
#11 0x0000000000453bda in boost::iterator_facade<boost::transform_iterator<boost::algorithm::detail::copy_iterator_rangeF<std::string,
__gnu_cxx::__normal_iterator<char*, std::string> >, boost::algorithm::split_iterator<__gnu_cxx::__normal_iterator<char*, std::string> >, boost::use_default, boost::use_default>, std::string, boost::forward_traversal_tag, std::string, long>::operator++ (this=0x7fffff3ff450) at /med/build/boost/boost_1_43_0/boost/iterator/iterator_facade.hpp:664
#12 0x000000000045326d in std::vector<std::string, std::allocator<std::string>
>::_M_range_initialize<boost::transform_iterator<boost::algorithm::detail::copy_iterator_rangeF<std::string,
__gnu_cxx::__normal_iterator<char*, std::string> >, boost::algorithm::split_iterator<__gnu_cxx::__normal_iterator<char*, std::string> >, boost::use_default, boost::use_default> > (this=0x7fffff3ff6a0, __first=..., __last=...)
at /med/build/gcc/gcc-4.7.2/linux64/gcc-4.7.2/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:1157
#13 0x0000000000452aa8 in std::vector<std::string, std::allocator<std::string>
>::_M_initialize_dispatch<boost::transform_iterator<boost::algorithm::detail::copy_iterator_rangeF<std::string,
__gnu_cxx::__normal_iterator<char*, std::string> >, boost::algorithm::split_iterator<__gnu_cxx::__normal_iterator<char*, std::string> >, boost::use_default, boost::use_default> > (this=0x7fffff3ff6a0, __first=..., __last=...)
at /med/build/gcc/gcc-4.7.2/linux64/gcc-4.7.2/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:1148
#14 0x0000000000452206 in std::vector<std::string, std::allocator<std::string>
>::vector<boost::transform_iterator<boost::algorithm::detail::copy_iterator_rangeF<std::string,
__gnu_cxx::__normal_iterator<char*, std::string> >, boost::algorithm::split_iterator<__gnu_cxx::__normal_iterator<char*, std::string> >, boost::use_default, boost::use_default> > (
this=0x7fffff3ff6a0, __first=..., __last=..., __a=...)
at /med/build/gcc/gcc-4.7.2/linux64/gcc-4.7.2/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:393
#15 0x0000000000451a87 in boost::algorithm::iter_split<std::vector<std::string, std::allocator<std::string> >, std::string, boost::algorithm::detail::token_finderF<boost::algorithm::detail::is_any_ofF<char>
> > (Result=..., Input=..., Finder=...) at /med/build/boost/boost_1_43_0/boost/algorithm/string/iter_find.hpp:178
function used as foloows in the code :
boost::split(signals, name, boost::is_any_of("."), boost::token_compress_on);
template<typename Derived>
struct predicate_facade {};
In above code, i am getting can not access memory error in gdb for this pointer :
(gdb) p this Cannot access memory at address 0x7fffff3feff8
But it worked fine in small code (tried on ideone):
https://www.ideone.com/jnB037
Please help me out.
Thanks in advance

boost and c++11 thread compatibility [duplicate]

This question already has answers here:
Is it smart to replace boost::thread and boost::mutex with c++11 equivalents?
(7 answers)
Closed 9 years ago.
have a code which used to run fine with boost thread under ubuntu. it's basic read only data sharing multithreading. I try to use C++11 instead of boost, very basic transition. the code compiles but have subtle bugs. crashes randomly with C++11 std thread. tried to use valgrind drd, but hard to read the debug info. Any thoughts?
==19608== Conflicting load by thread 3 at 0x00643be8 size 8
==19608== at 0x41CEBA: std::subtract_with_carry_engine<unsigned int, 24ul, 10ul, 24ul>::operator()() (random.tcc:601)
==19608== by 0x41CD6C: double std::generate_canonical<double, 53ul, std::subtract_with_carry_engine<unsigned int, 24ul, 10ul, 24ul> >(std::subtract_with_carry_engine<unsigned int, 24ul, 10ul, 24ul>&) (random.tcc:3475)
==19608== by 0x41CB06: std::__detail::_Adaptor<std::subtract_with_carry_engine<unsigned int, 24ul, 10ul, 24ul>, double>::operator()() (random.h:190)
==19608== by 0x41C877: double std::normal_distribution<double>::operator()<std::subtract_with_carry_engine<unsigned int, 24ul, 10ul, 24ul> >(std::subtract_with_carry_engine<unsigned int, 24ul, 10ul, 24ul>&, std::normal_distribution<double>::param_type const&) (random.tcc:1950)
==19608== by 0x41C688: double std::normal_distribution<double>::operator()<std::subtract_with_carry_engine<unsigned int, 24ul, 10ul, 24ul> >(std::subtract_with_carry_engine<unsigned int, 24ul, 10ul, 24ul>&) (random.h:2196)
==19608== by 0x41C379: nrand(double, double) (NRand.cpp:8)
==19608== by 0x416F78: ClassDef::set_x() (LoanDef.h:407)
==19608== by 0x4168CA: Sim(std::vector<ClassDef, std::allocator<ClassDef> >&, Assumption&, std::unordered_map<std::string, std::vector<double, std::allocator<double> >, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, std::vector<double, std::allocator<double> > > > >&, unsigned int, NextStepCalcML&, std::vector<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >, std::allocator<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > > >&, unsigned int, unsigned int) (NewSim.cpp:105)
==19608== by 0x411A09: _ZNSt12_Bind_simpleIFPFvRSt6vectorI7LoanDefSaIS1_EER10AssumptionRSt13unordered_mapISsS0_IdSaIdEESt4hashISsESt8equal_toISsESaISt4pairIKSsS9_EEEjR14NextStepCalcMLRS0_IS0_IS9_SaIS9_EESaISN_EEjjESt17reference_wrapperIS3_EST_IS5_EST_ISI_EjST_ISK_EST_ISP_EjjEE9_M_invokeIILm0ELm1ELm2ELm3ELm4ELm5ELm6ELm7EEEEvSt12_Index_tupleIIXspT_EEE (functional:1732)
==19608== by 0x4116AE: std::_Bind_simple<void (*()(std::reference_wrapper<std::vector<LoanDef, std::allocator<LoanDef> > >, std::reference_wrapper<Assumption>, std::reference_wrapper<std::unordered_map<std::string, std::vector<double, std::allocator<double> >, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, std::vector<double, std::allocator<double> > > > > >, unsigned int, std::reference_wrapper<NextStepCalcML>, std::reference_wrapper<std::vector<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >, std::allocator<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > > > >, unsigned int, unsigned int))(std::vector<LoanDef, std::allocator<ClassDef> >&, Assumption&, std::unordered_map<std::string, std::vector<double, std::allocator<double> >, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, std::vector<double, std::allocator<double> > > > >&, unsigned int, NextStep&, std::vector<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >, std::allocator<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > > >&, unsigned int, unsigned int)>::operator()() (functional:1720)
==19608== by 0x411647: std::thread::_Impl<std::_Bind_simple<void (*()(std::reference_wrapper<std::vector<ClassDef, std::allocator<ClassDef> > >, std::reference_wrapper<Assumption>, std::reference_wrapper<std::unordered_map<std::string, std::vector<double, std::allocator<double> >, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, std::vector<double, std::allocator<double> > > > > >, unsigned int, std::reference_wrapper<NextStep>, std::reference_wrapper<std::vector<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >, std::allocator<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > > > >, unsigned int, unsigned int))(std::vector<LoanDef, std::allocator<LoanDef> >&, Assumption&, std::unordered_map<std::string, std::vector<double, std::allocator<double> >, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, std::vector<double, std::allocator<double> > > > >&, unsigned int, NextStep&, std::vector<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >, std::allocator<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > > >&, unsigned int, unsigned int)> >::_M_run() (thread:115)
thank you. btw, I tried to use this random head file I wrote, not sure if it's safe under multithread environment. it used to work fine with boost.
myrand.hpp
#ifndef NRAND_H
#define NRAND_H
#include <random>
double nrand(double mean = 0., double sd = 1.);
double urand(double a=0., double b=0.);
#endif
and myrand.cpp
#include "NRand.h"
using namespace std;
double nrand(double mean, double sd) {
static random_device rd;
static subtract_with_carry_engine<unsigned,24,10,24> e(rd());
normal_distribution<> dist(mean, sd);
return dist(e);
}
double urand(double a, double b) {
static random_device rd;
static subtract_with_carry_engine<unsigned,24,10,24> e(rd());
uniform_real_distribution<> dist(a, b);
return dist(e);
}
many thanks.
IMHO, your code is not threadsafe and hence should not work correctly under C++11. I think the problem is that the static variables rd and e are global variables but not protected (by mutex), so concurrent calls will race.
Presumably, you can make this code threadsafe by making those variables thread_local, but I have no experience.