[英]Unexpected variable value using Boost.Asio
我從boost.asio項目中發現了一些奇怪的問題。 所以我做了一個示例控制台項目,發生了同樣的問題。
這是代碼:
class server
{
public:
server()
: m_acceptor(m_ios)
{
m_work.reset(new boost::asio::io_service::work(m_ios));
m_thread = boost::thread(boost::bind(&boost::asio::io_service::run, &m_ios));
}
virtual ~server()
{
m_work.reset();
m_ios.stop();
m_thread.join();
}
void do_test()
{
m_ios.post(boost::bind(&server::handle_test, this));
}
private:
void handle_test()
{
m_value = 1234;
printf("server::handle_test() -> m_value %d.\n", m_value);
}
boost::shared_ptr<boost::asio::io_service::work> m_work;
boost::asio::io_service m_ios;
boost::thread m_thread;
boost::asio::ip::tcp::acceptor m_acceptor;
public:
int m_value;
};
void main()
{
server s;
s.do_test();
_getch(); // wait for a while
printf("main() -> m_value is %d.\n", s.m_value);
_getch();
}
好。 因此,使用此代碼,控制台輸出將是:
server :: handle_test()-> m_value為1234。
main()-> m_value是1234。
按任意鍵繼續 。 。 。
對??
但是奇怪的是,實際的控制台輸出是:
server :: handle_test()-> m_value為1234。
main()-> m_value為0。
按任意鍵繼續 。 。 。
為什么???
有誰能解釋這個嗎? 我該如何從根本上解決它?
這是整個項目文件和exe。 https://www.dropbox.com/s/cflcmbuwgab1rxb/boost_asio_test.zip?dl=0
[測試環境]
Windows Embedded 8.1 Industry Pro x64
與Visual Studio 2013一起編譯(VisualStudioVersion 12.0.31101.0)
您不同步從多個線程對共享數據的訪問。
這是數據競賽。
數據競爭是未定義的行為 。 什么都可能發生。
通過同步對m_value
訪問來修復它
更新
啟用線程清理程序(gcc / clang上為-fsanitizer=thread
)時,您會獲得有關Live On Coliru的非常具體的報告
==================
WARNING: ThreadSanitizer: data race (pid=27230)
Read of size 4 at 0x7fff488eb360 by main thread:
#0 main /tmp/test.cpp:57 (test+0x0000004e2d82)
Previous write of size 4 at 0x7fff488eb360 by thread T1:
#0 server::handle_test() /tmp/test.cpp:36 (test+0x00000051259c)
#1 boost::_mfi::mf0<void, server>::operator()(server*) const /home/sehe/custom/boost/boost/bind/mem_fn_template.hpp:49 (test+0x00000051741e)
#2 void boost::_bi::list1<boost::_bi::value<server*> >::operator()<boost::_mfi::mf0<void, server>, boost::_bi::list0>(boost::_bi::type<void>, boost::_mfi::mf0<void, server>&, boost::_bi::list0&, int) /home/sehe/custom/boost/boost/bind/bind.hpp:255 (test+0x00000051705a)
#3 boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > >::operator()() /home/sehe/custom/boost/boost/bind/bind.hpp:895 (test+0x000000516cbf)
#4 void boost::asio::asio_handler_invoke<boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > > >(boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > >&, ...) /home/sehe/custom/boost/boost/asio/handler_invoke_hook.hpp:69 (test+0x000000516a35)
#5 void boost_asio_handler_invoke_helpers::invoke<boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > >, boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > > >(boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > >&, boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > >&) /home/sehe/custom/boost/boost/asio/detail/handler_invoke_helpers.hpp:37 (test+0x0000005167e0)
#6 boost::asio::detail::completion_handler<boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > > >::do_complete(boost::asio::detail::task_io_service*, boost::asio::detail::task_io_service_operation*, boost::system::error_code const&, unsigned long) /home/sehe/custom/boost/boost/asio/detail/completion_handler.hpp:68 (test+0x0000005162b7)
#7 boost::asio::detail::task_io_service_operation::complete(boost::asio::detail::task_io_service&, boost::system::error_code const&, unsigned long) /home/sehe/custom/boost/boost/asio/detail/task_io_service_operation.hpp:38 (test+0x000000532a63)
#8 boost::asio::detail::task_io_service::do_run_one(boost::asio::detail::scoped_lock<boost::asio::detail::posix_mutex>&, boost::asio::detail::task_io_service_thread_info&, boost::system::error_code const&) /home/sehe/custom/boost/boost/asio/detail/impl/task_io_service.ipp:372 (test+0x00000052db18)
#9 boost::asio::detail::task_io_service::run(boost::system::error_code&) /home/sehe/custom/boost/boost/asio/detail/impl/task_io_service.ipp:149 (test+0x00000052721a)
#10 boost::asio::io_service::run() /home/sehe/custom/boost/boost/asio/impl/io_service.ipp:59 (test+0x0000005266ce)
#11 server::worker() /tmp/test.cpp:17 (test+0x000000518f19)
#12 boost::_mfi::mf0<void, server>::operator()(server*) const /home/sehe/custom/boost/boost/bind/mem_fn_template.hpp:49 (test+0x00000051741e)
#13 void boost::_bi::list1<boost::_bi::value<server*> >::operator()<boost::_mfi::mf0<void, server>, boost::_bi::list0>(boost::_bi::type<void>, boost::_mfi::mf0<void, server>&, boost::_bi::list0&, int) /home/sehe/custom/boost/boost/bind/bind.hpp:255 (test+0x00000051705a)
#14 boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > >::operator()() /home/sehe/custom/boost/boost/bind/bind.hpp:895 (test+0x000000516cbf)
#15 boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > > >::run() /home/sehe/custom/boost/boost/thread/detail/thread.hpp:116 (test+0x00000051d5a9)
#16 thread_proxy thread.cpp (libboost_thread.so.1.59.0+0x000000011aa9)
As if synchronized via sleep:
#0 nanosleep <null> (test+0x000000475c10)
#1 boost::this_thread::hiden::sleep_for(timespec const&) <null> (libboost_thread.so.1.59.0+0x000000012885)
#2 void boost::this_thread::sleep_for<long, boost::ratio<1l, 1000l> >(boost::chrono::duration<long, boost::ratio<1l, 1000l> > const&) /home/sehe/custom/boost/boost/thread/v2/thread.hpp:112 (test+0x0000004e65fb)
#3 main /tmp/test.cpp:56 (test+0x0000004e2b71)
Location is stack of main thread.
Thread T1 (tid=27234, running) created by main thread at:
#0 pthread_create <null> (test+0x00000047aaf1)
#1 boost::thread::start_thread_noexcept() <null> (libboost_thread.so.1.59.0+0x000000010ea9)
#2 thread<boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server *> > > > /home/sehe/custom/boost/boost/thread/detail/thread.hpp:266 (test+0x000000519122)
#3 server /tmp/test.cpp:13 (test+0x0000004e58b3)
#4 main /tmp/test.cpp:53 (test+0x0000004e2855)
SUMMARY: ThreadSanitizer: data race /tmp/test.cpp:57 main
==================
server::handle_test() -> m_value 1234
main() -> m_value is 1234
ThreadSanitizer: reported 1 warnings
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.