1

如果我打电话

concurrency::create_task([self,this]() -> concurrency::task<void>
{ 
   co_await 5s; //or really any task that suspends until complete
   MemberFunction();
   co_return;
});

在我调用 MemberFunction() 的暂停点之后,this 指针为 NULL,并且 self 上的析构函数已被调用,因为虽然代码段和本地函数堆栈已恢复,但最初用作仿函数的实际 lambda 对象已经退出范围。ASIO 捕获函子并将其保持在范围内,直到它完成执行,但 PPL 并发运行时似乎没有。在 co_await 没有在挂起之前将所有捕获变量复制到本地函数堆栈后,我如何保持状态(这确实有效,但可维护性是噩梦)?我尝试将 create_task 返回的任务放入一个变量中并将其存储到任务完成,但这并没有帮助,并且查看代码看起来它似乎没有努力将仿函数保持在范围内,直到它完成。

4

1 回答 1

0

来自https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines

“正常 lambda 的正确使用模式对于协程 lambda 来说是危险的。捕获变量的明显模式将导致在第一个暂停点之后访问释放的内存,即使对于引用的智能指针和可复制类型也是如此。”

坏的:

int value = get_value();
std::shared_ptr<Foo> sharedFoo = get_foo();
{
  const auto lambda = [value, sharedFoo]() -> std::future<void>
  {
    co_await something();
    // "sharedFoo" and "value" have already been destroyed
    // the "shared" pointer didn't accomplish anything
  };
  lambda();
} // the lambda closure object has now gone out of scope

好的:

int value = get_value();
std::shared_ptr<Foo> sharedFoo = get_foo();
{
  // take as by-value parameter instead of as a capture
  const auto lambda = [](auto sharedFoo, auto value) -> std::future<void>
  {
    co_await something();
    // sharedFoo and value are still valid at this point
  };
  lambda(sharedFoo, value);
} // the lambda closure object has now gone out of scope

最好的:

std::future<void> Class::do_something(int value, std::shared_ptr<Foo> sharedFoo)
{
  co_await something();
  // sharedFoo and value are still valid at this point
}

void SomeOtherFunction()
{
  int value = get_value();
  std::shared_ptr<Foo> sharedFoo = get_foo();
  do_something(value, sharedFoo);
}
于 2022-01-20T14:53:16.977 回答