首页 > 解决方案 > 为什么 async() 在临时变量上写入并且没有发生崩溃

问题描述

这是我编写的一些代码,用于测试 async() 对临时变量的写入。函数测试使用 async() 执行函数 write_A(A* a),并使用 future.wait_for() 等待一段时间的结果。如果超时,则测试返回,A a2 将同时被释放,因为它是在堆栈上分配的。写在 A* a 上的 write_A 会崩溃。但实际上该程序运行良好。为什么异步执行的函数 write_A 可以写入已释放的堆栈临时变量?

struct A {
  string name;
  string address;
};

int write_A(A* a) {
  sleep(3);
  a->name = "tractor";
  a->address = "unknow";
  cout <<"write_A return" << endl;
  return 0;
}

void test(A* a) {
   A a2;
  future<int> fut = async(launch::async, write_A, &a2);
  auto status = fut.wait_for(chrono::milliseconds(1000));
  if (status == future_status::ready) {
    int ret = fut.get();
    *a = a2;
    cout <<"succ"<<endl;
  } else {
    cout <<"timeout"<<endl;
  }
}

void test2() {
  A a;
  test(&a);
}

int main ()
{
  test2();
  sleep(5);
  return 0;
}

我预计程序会崩溃,因为 write_A 在测试返回时已释放的对象指针上写入。但是程序输出:

暂停

write_A 返回

标签: c++11asynchronousfuture

解决方案


这个对象

    future<int> fut

test在函数结束时被销毁。当调用future 析构函数时,它会阻塞直到共享状态准备好——这意味着write_A结束。因此,指向a内部test函数的指针始终有效。

本地对象以与其创建相反的顺序被销毁,所以在这种情况下

A a2;
future<int> fut = async(launch::async, write_A, &a2);

由于 firstfut被删除,它的析构函数一直等待直到write_A完成。然后a2被破坏。


推荐阅读