C++11:带有 std::thread 和 lambda 函数的段错误

标签 c++ c++11 segmentation-fault pthreads stdthread

我已经写了一个小应用程序来演示这个问题,它不是很漂亮,但它完成了工作。

#include <functional>
#include <iostream>
#include <mutex>
#include <queue>
#include <thread>

class A {
 public:
  A() : thread_(), tasks_(), mutex_(), a_(99999) {}

  void Start() {
    thread_ = std::thread([this] () { Run(); });
  }

 private:
  using Task = std::function<void()>;

 public:
  void AddTask(const Task& task) {
    std::lock_guard<std::mutex> lock(mutex_);

    tasks_.push(task);
  }

  bool Empty() {
    std::lock_guard<std::mutex> lock(mutex_);

    const bool empty = tasks_.empty();

    return empty;
  }

  Task GetTask() {
    std::lock_guard<std::mutex> lock(mutex_);

    const auto& task = tasks_.front();

    tasks_.pop();

    return task;
  }

  int GetInt() { return a_; }

  void Join() { thread_.join(); }

 private:
  void Run() {
    while (Empty());

    (GetTask())();
  }

  std::thread thread_;
  std::queue<Task> tasks_;
  std::mutex mutex_;
  int a_;
};

template <class Base>
class B : public Base {
 public:
  using Base::Base;

  void Start() {
    Base::Start();
std::cout << "A: " << this << std::endl;
    Base::AddTask([this] () { std::cout << "T: " << this << std::endl; Do(); });
  }

  void Do() {
    std::cout << "Do: " << this << std::endl;
    std::cout << "GetInt: " << Base::GetInt() << std::endl;
  }
};

int main() {
  B<A> app;
  app.Start();
  app.Join();
}

clang++ -std=c++11 -lpthread test_a.cpp

A: 0x7ffeb521f4e8
T: 0x21ee540
Do: 0x21ee540
GetInt: 0

请注意“this”的变化以及“GetInt”的值 0。

我真的迷路了...任何帮助将不胜感激,

谢谢。

最佳答案

我将你的复制品缩减为:

#include <functional>
#include <iostream>
#include <queue>

struct foo {
  using Task = std::function<void()>;

  void Test() {
    std::cout << "In Test, this: " << this << std::endl;
    AddTask([this] { std::cout << "In task, this: " << this << std::endl; });
  }

  void AddTask(const Task& task) {
    tasks_.push(task);
  }

  Task GetTask() {
    const auto& task = tasks_.front();
    tasks_.pop();
    return task;
  }

  std::queue<Task> tasks_;
};

int main() {
  foo f;
  f.Test();
  auto func = f.GetTask();
  func();
}

你现在看到问题了吗?问题在于:

const auto& task = tasks_.front();
tasks_.pop();

这里您获取了一个对象的引用,然后您告诉队列继续并删除该对象。您的引用现在悬而未决,随之而来的是困惑。

您应该将其移出:

Task GetTask() {
  auto task = std::move(tasks_.front());
  tasks_.pop();
  return task;
}

关于C++11:带有 std::thread 和 lambda 函数的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39988840/

相关文章:

c++ - std::map 具有不同数据类型的值

c++ - const * const 的预处理器简写

c++ - 使用任何数字返回数字的无符号函数

c++ - 即使有显式实例化,也没有为显式专用模板生成代码

c++11 努力理解为什么我不能统一初始化一个结构,但我可以初始化一个类似类型的 std::pair

c - 分段故障核心转储......?

c++ - 对 operator+ 和/或 operator+= 使用 move 语义有意义吗?

c++ - 如何返回映射到可变参数位置的类型

c - GDB 调试器的段错误 - C

c - 如何正确动态分配内存?