【问题标题】:Is it legal to return address of local coroutine variable in C++?在 C++ 中返回本地协程变量的地址是否合法?
【发布时间】:2021-09-24 03:21:39
【问题描述】:

如果我返回本地协程变量的地址,例如通过承诺,它是否保证符合 C++ 标准?考虑一个例子(基于https://www.scs.stanford.edu/~dm/blog/c++-coroutines.html):

#include <coroutine>
#include <iostream>

struct ReturnObject {
  struct promise_type {
    unsigned * value_ = nullptr;

    void return_void() {}
    ReturnObject get_return_object() {
      return {
        .h_ = std::coroutine_handle<promise_type>::from_promise(*this)
      };
    }
    std::suspend_never initial_suspend() { return {}; }
    std::suspend_never final_suspend() noexcept { return {}; }
    void unhandled_exception() {}
  };

  std::coroutine_handle<promise_type> h_;
  operator auto() const { return h_; }
};

template<typename PromiseType>
struct GetPromise {
  PromiseType *p_;
  bool await_ready() { return false; }
  bool await_suspend(std::coroutine_handle<PromiseType> h) {
    p_ = &h.promise();
    return false;
  }
  PromiseType *await_resume() { return p_; }
};

ReturnObject counter()
{
  auto pp = co_await GetPromise<ReturnObject::promise_type>{};

  for (unsigned i = 0;; ++i) {
    pp->value_ = &i; // is it legal?
    co_await std::suspend_always{};
  }
}

int main()
{
  std::coroutine_handle<ReturnObject::promise_type> h = counter();
  auto &promise = h.promise();
  for (int i = 0; i < 5; ++i) {
    std::cout << "counter: " << *promise.value_ << std::endl;
    h();
  }
  h.destroy();
}

https://gcc.godbolt.org/z/P5PMc15qW

在实践中我发现它确实有效,但它真的合法吗?

【问题讨论】:

    标签: c++ c++20 c++-coroutine


    【解决方案1】:

    是的,这是合法的。 counter 的局部变量存储在 h 拥有的动态分配对象中。

    存在释放后使用可能性的常见警告,即promise 悬挂在h.destroy() 之后。

    【讨论】:

      【解决方案2】:

      它在某些情况下可以工作,但这不是编写程序的好方法。指针指向的内存单元可以(并且可能很快)被其他变量覆盖。尝试在循环之前编写一些代码(声明一些变量)并再次检查结果。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-23
        • 1970-01-01
        • 2023-04-05
        • 2018-03-22
        • 2014-09-24
        • 2020-05-07
        相关资源
        最近更新 更多