boost::regex_match线程安全疑问:ThreadSanitizer竞态条件是否为误报?
ThreadSanitizer检测boost::regex_match竞态条件的误报分析
问题背景
- ThreadSanitizer检测到
boost::regex_match存在竞态条件,但认为这是误报。 - 调用栈中未发现依赖
BOOST_HAS_THREADS的同步原语。 - 所有输入参数均位于各自线程的栈内存中,不存在共享数据访问的情况。
ThreadSanitizer警告日志
================== 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
误报分析
- 内存归属判断:竞态涉及的堆内存由线程T105分配,属于
save_state_init为perl_matcher实例创建的内部状态块。每个线程调用regex_match时会生成独立的perl_matcher实例,理论上不会跨线程共享该内存块。 - 栈回溯问题:线程T105的栈回溯未能完整恢复,可能是TSAN的栈解析误差,导致无法确认该内存块是否已被正确释放并复用,进而误判为共享访问。
- 无共享数据佐证:所有输入参数均为线程栈私有,调用栈中也未发现缺失同步原语的情况,符合线程安全的调用场景。
综上,该警告大概率是ThreadSanitizer的误报,可能源于内存分配器的内存复用机制被错误识别为竞态访问。
内容的提问来源于stack exchange,提问作者Desperado17
相关产品推荐
相关产品推荐

