我正在尝试使用 std::async 在 C++ 中使用 futures 进行一些多线程处理。我需要创建一堆对象,其构造函数并行执行一些序列化。我正在调用一个函数,该函数调用构造函数并向对象返回一个 shared_ptr
。我使用 std::async 调用此函数,并创建此函数返回的 futures vector ,然后在我假设的循环中对每个 future 调用 .get()
将是一个阻塞调用,但这就是我在调试器中遇到异常的地方。我不确定发生了什么。
这是一个可重现示例的简化版本,当使用 C++17 编译时,该示例会在 MSVC 14.3+ 中引发异常
#include <iostream>
#include <vector>
#include <future>
#include <memory>
#include <numeric>
struct TaskUnit {
std::vector<int> preds;
int vertex;
};
struct Task {
std::vector<TaskUnit> units;
int task_id;
Task(std::vector<TaskUnit> const& units, int const task_id)
: units(units), task_id(task_id) {}
static std::shared_ptr<Task const>
Create(std::vector<TaskUnit> const& units, int const id)
{
return std::make_shared<Task const>(units, id);
}
};
auto ConstructTask(int const task_count)
{
std::vector<TaskUnit> units{ {{1,2}, 1}};
return std::async(std::launch::async, Task::Create, std::cref(units), task_count);
}
auto ConstructTasks(int const n_tasks)
{
std::vector<std::future<std::shared_ptr<Task const>>> futures;
std::vector<int> range(n_tasks);
std::iota(range.begin(), range.end(), 0);
for (auto const& task_count : range)
{
futures.push_back(ConstructTask(task_count));
}
std::vector<std::shared_ptr<Task const>> tasks;
for (auto& future : futures)
{
tasks.push_back(future.get());
}
return tasks;
}
int main()
{
auto tasks = ConstructTasks(10);
for (auto const& task : tasks)
{
std::cout << task->task_id;
}
}
最佳答案
您传递对 std::vector<TaskUnit>
的引用当函数返回时,它会超出范围并终止。按值传递:
class Task {
static std::shared_ptr<Task const>
Create(std::vector<TaskUnit> const& units, int const id)
// ^ remove
{
return std::make_shared<Task const>(units, id);
}
};
auto ConstructTask(int const task_count) {
std::vector<TaskUnit> units{{{1, 2}, 1}};
return std::async(std::launch::async, Task::Create, units, task_count);
// ^^^^^ remove cref
}
关于Future 访问冲突的 C++ vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75422382/