[英]C++11: Segfault with std::thread and lambda function
I've written a small application to demonstrate the issue, it is not pretty, but it does the job.我写了一个小应用程序来演示这个问题,它并不漂亮,但它完成了工作。
#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 clang++ -std=c++11 -lpthread test_a.cpp
A: 0x7ffeb521f4e8
T: 0x21ee540
Do: 0x21ee540
GetInt: 0
Notice the change in 'this' and the value of 0 for 'GetInt'.注意'this'的变化和'GetInt'的值0。
I'm really lost here... Any help would be greatly appreciated,我真的在这里迷路了......任何帮助将不胜感激,
Thanks.谢谢。
I reduced your reproduction to:我将您的复制减少到:
#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();
}
Do you see the problem now?你现在看到问题了吗? The issue lies with:
问题在于:
const auto& task = tasks_.front();
tasks_.pop();
Here you grab a reference to an object, then you tell the queue to go ahead and delete that object.在这里,您获取对对象的引用,然后告诉队列继续并删除该对象。 Your reference is now dangling, and chaos ensues.
您的参考现在悬而未决,随之而来的是混乱。
You should move it out instead:您应该将其移出:
Task GetTask() {
auto task = std::move(tasks_.front());
tasks_.pop();
return task;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.