使用Boost.Asio的意外变量值

时间:2015-11-11 23:31:27

标签: c++ boost 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() - &gt; m_value是1234。

     

main() - &gt; m_value是1234。

     

按任意键继续。 。

右??

但奇怪的是,实际的控制台输出是:

  

server :: handle_test() - &gt; m_value是1234。

     

main() - &gt; 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)

1 个答案:

答案 0 :(得分:0)

您不能同步访问来自多个线程的共享数据。

这是数据竞赛。

数据竞赛是Undefined Behaviour。任何事情都可能发生。

通过同步对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