在vector成员变量中存储thread触发断点
Storing thread in vector member variable triggers breakpoint
我有一个名为 Executor 的 class,它有一个 vector 作为成员变量。 submit(const std::function& f) 成员函数应该将传递的 lambda 作为线程启动并将其添加到向量中。析构函数连接存储在向量中的所有线程。
第一个 lambda 打印结果,但之后我的代码不知何故遇到了断点。
我做错了什么?
这是我的 Executor.h 代码:
#include <thread>
#include <mutex>
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
class Executor
{
protected:
vector<thread*> threads;
mutex m;
public:
void submit(const std::function<void()>& f);
Executor();
~Executor();
};
Executor.cpp:
#include "Executor.h"
void Executor::submit(const std::function<void()>& f)
{
{
lock_guard<mutex> lock(m);
thread t(f);
threads.push_back(&t);
}
}
Executor::Executor() {}
Executor::~Executor()
{
for (unsigned int i = 0; i < threads.size(); i++)
{
threads.at(i)->join();
delete threads.at(i);
}
threads.clear();
}
和 main():
Executor ex;
auto fact = [](){cout<< "factor(55) = " << factor(55); };
auto pk = [](){cout << "P2(100, 50) = " << P2(100, 50); };
auto fib = [](){cout << "fibonacci(45) = " << fibonacci(45); };
ex.submit(fact);
ex.submit(pk);
ex.submit(fib);
在 threads.push_back(&t);
中,指针 &t
仅在声明 t
的范围结束之前有效。这会导致 3 个问题:
- 在
submit
内范围的末尾,线程在未调用 join
的情况下被破坏,导致 std::terminate
被调用
- 在
Executor
的析构函数中 ->join
在悬空指针上调用
- 在
Executor
的析构函数中,您调用了 delete
未分配给 new
的内容
在这段代码中不需要使用指针,如果你将线程直接存储在向量中你的代码会更简单和更安全:
class Executor
{
protected:
vector<thread> threads;
mutex m;
public:
void submit(const std::function<void()>& f);
Executor();
~Executor();
Executor(const Executor&) = delete;
Executor& operator=(const Executor&) = delete;
};
void Executor::submit(const std::function<void()>& f)
{
{
lock_guard<mutex> lock(m);
threads.emplace_back(f);
}
}
Executor::Executor() {}
Executor::~Executor()
{
for (auto& thread : threads)
{
thread.join();
}
threads.clear();
}
注意我还删除了复制构造函数和赋值运算符以符合 rule of three
我有一个名为 Executor 的 class,它有一个 vector
这是我的 Executor.h 代码:
#include <thread>
#include <mutex>
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
class Executor
{
protected:
vector<thread*> threads;
mutex m;
public:
void submit(const std::function<void()>& f);
Executor();
~Executor();
};
Executor.cpp:
#include "Executor.h"
void Executor::submit(const std::function<void()>& f)
{
{
lock_guard<mutex> lock(m);
thread t(f);
threads.push_back(&t);
}
}
Executor::Executor() {}
Executor::~Executor()
{
for (unsigned int i = 0; i < threads.size(); i++)
{
threads.at(i)->join();
delete threads.at(i);
}
threads.clear();
}
和 main():
Executor ex;
auto fact = [](){cout<< "factor(55) = " << factor(55); };
auto pk = [](){cout << "P2(100, 50) = " << P2(100, 50); };
auto fib = [](){cout << "fibonacci(45) = " << fibonacci(45); };
ex.submit(fact);
ex.submit(pk);
ex.submit(fib);
在 threads.push_back(&t);
中,指针 &t
仅在声明 t
的范围结束之前有效。这会导致 3 个问题:
- 在
submit
内范围的末尾,线程在未调用join
的情况下被破坏,导致std::terminate
被调用 - 在
Executor
的析构函数中->join
在悬空指针上调用 - 在
Executor
的析构函数中,您调用了delete
未分配给new
的内容
在这段代码中不需要使用指针,如果你将线程直接存储在向量中你的代码会更简单和更安全:
class Executor
{
protected:
vector<thread> threads;
mutex m;
public:
void submit(const std::function<void()>& f);
Executor();
~Executor();
Executor(const Executor&) = delete;
Executor& operator=(const Executor&) = delete;
};
void Executor::submit(const std::function<void()>& f)
{
{
lock_guard<mutex> lock(m);
threads.emplace_back(f);
}
}
Executor::Executor() {}
Executor::~Executor()
{
for (auto& thread : threads)
{
thread.join();
}
threads.clear();
}
注意我还删除了复制构造函数和赋值运算符以符合 rule of three