Boost::thread 在简单循环期间崩溃

Posted

技术标签:

【中文标题】Boost::thread 在简单循环期间崩溃【英文标题】:Boost::thread crashes during simple loop 【发布时间】:2014-12-05 11:48:41 【问题描述】:

我正在尝试一些简单的boost::thread代码,如下:

#include <iostream>
#include <boost/thread.hpp>

void InputLoop()

    std::cout << "Loop start" << std::endl;

    int y = 0;
    while (1)
    
        std::cout << "y = " << y << std::endl;
        y++;
    

    std::cout << "Loop end" << std::endl;


int main()

    std::cout << "Main start" << std::endl;

    boost::thread t(InputLoop);
    t.start_thread();

    while (1)
    
        int x = 0;
    

    std::cout << "Main end" << std::endl;

    return 0;

这给出了输出:

Main start
Loop start
y = 0
y = 1
y = 2
.
.
.
The program has unexpectedly finished

所以,它在InputLoop() 期间崩溃了。发生崩溃时y的值在不同的运行中有所不同,范围从大约0到大约10000。

发生了什么事?

【问题讨论】:

它在coliru.stacked-crooked.com 上运行。虽然,没有 t.start_thread();并带有“警告:未使用的变量'x' [-Wunused-variable] int x = 0;” 我需要升级或降级我的 boost-pick。因为start_thread 在我的平台上声明private 访问权限(OSX 10.7.1) @WhozCraig - 抱歉,已编辑,忘记提及 - "/usr/local/include/boost/thread/detail/thread.hpp:177:14: error: 'void boost::thread: :start_thread()' 是私有的 void start_thread()"。只是想指出它不会“意外崩溃”。 【参考方案1】:

你不应该调用 start_thread 吗?

这不是必需的,因为它是泄露的内部实现细节:

https://svn.boost.org/trac/boost/ticket/9632

在我的代码中,我不小心调用了这个方法,导致我的回调被启动了两次。

所以你获得了对std::couty的非同步访问,这导致Undefined Behaviour

在此提交中找到修复:https://github.com/boostorg/thread/commit/750c849b0f0dff79a289111955260a4147ac7f59

【讨论】:

【参考方案2】:

即使在class thread一个公共方法start_thread,它也不在documentation 中。那是reason:

启动线程

通过将可调用类型的对象传递给构造函数来启动新线程,该对象可以在没有参数的情况下调用。 [...]

如果您希望使用需要提供参数的函数或可调用对象来构造 boost::thread 的实例,可以通过向 boost::thread 构造函数传递额外的参数来完成:

不管你使用哪个构造函数,线程已经在运行:

// <boost/thread/detail/thread.hpp>
template <
  class F
>
explicit thread(BOOST_THREAD_RV_REF(F) f
//, typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
):
  thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f))))

    start_thread();

start_thread 是如何定义的?

void start_thread()

  if (!start_thread_noexcept())
  
    boost::throw_exception(thread_resource_error());
  

start_thread_noexcept实际上不在标题中,而是libboost_thread的一部分:

// boost/lib/thread/src/thread.cpp
bool thread::start_thread_noexcept()

    thread_info->self=thread_info;
    int const res = pthread_create(&thread_info->thread_handle, 0, &thread_proxy, thread_info.get());
    if (res != 0)
    
        thread_info->self.reset();
        return false;
    
    return true;

您实际上创建了两个线程。它(可能)是 thread_proxy 实现创建了您的行为。

【讨论】:

以上是关于Boost::thread 在简单循环期间崩溃的主要内容,如果未能解决你的问题,请参考以下文章

C++ boost::asio::io_service创建线程池thread_group简单实例

C++ boost::asio::io_service创建线程池thread_group简单实例

Boost.Thread 链接 - boost_thread 与 boost_thread-mt

哪个库用于迭代 1M*1k 次的并行 for 循环,OpenMP 或 boost::thread?

在 boost::thread 线程中使用异常

循环中的Boost Thread_Group非常慢