【问题标题】:Boost::thread crashes during simple loopBoost::thread 在简单循环期间崩溃
【发布时间】: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()"。只是想指出它不会“意外崩溃”。

标签: c++ boost boost-thread


【解决方案1】:

你不应该调用 start_thread 吗?

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

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

所以你获得了对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 实现创建了您的行为。

    【讨论】:

      猜你喜欢
      • 2010-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-28
      相关资源
      最近更新 更多