You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++使用std::async创建Futures向量时触发访问违规问题

问题分析与修复

核心问题:悬空引用触发未定义行为

你的代码中,ConstructTask函数通过std::cref(units)将局部变量units的引用传递给std::async的异步任务,但units是ConstructTask的局部对象——函数执行完毕返回后,该局部对象会立即销毁。而异步任务可能在ConstructTask返回后才启动执行,此时引用已变为悬空状态,访问该引用会触发未定义行为,表现为调试器抛出异常。

修复方案

移除std::cref,直接传递units的值,让异步任务获得独立的对象副本,彻底避免引用悬空问题:
std::async会自动拷贝参数传递给异步函数,传递值后,异步任务将持有units的独立副本,即使原局部对象销毁,副本依然有效。

修正后的代码

#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}};
  // 移除std::cref,直接传递units的值
  return std::async(std::launch::async, Task::Create, 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;
    }
}

额外优化建议

如果实际场景中units对象体积较大、拷贝成本高,可以采用两种替代方案:

  • 在ConstructTask中用std::make_shared创建units的共享副本,传递std::shared_ptr给异步任务,确保对象生命周期覆盖异步任务执行全程。
  • 将units的创建逻辑移到异步任务内部,避免跨线程传递大对象或引用。

内容的提问来源于stack exchange,提问作者Bilentor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 12:25:14