c++ - 恢复生命周期已经结束的对象的成员函数协程是UB吗?

标签 c++ language-lawyer c++20 c++-coroutine

这个问题源于这个评论:Lambda lifetime explanation for C++20 coroutines

关于这个例子:

auto foo() -> folly::coro::Task<int> {
    auto task = []() -> folly::coro::Task<int> {
        co_return 1;
    }();
    return task;
}

所以问题是是否执行foo返回的协程会导致UB。

“调用”成员函数(在对象的生命周期结束后)是 UB:http://eel.is/c++draft/basic.life#6.2

...any pointer that represents the address of the storage location where the object will be or was located may be used but only in limited ways. [...] The program has undefined behavior if:

[...]

-- the pointer is used to access a non-static data member or call a non-static member function of the object, or



但是,在这个例子中:
  • ()在 lambda 的生命周期仍然有效时调用 lambda 的运算符
  • 然后它被挂起,
  • 然后 lambda 被销毁,
  • 然后成员函数(运算符 () )在之后的某个时间点恢复。

  • 此恢复是否被视为未定义行为?

    最佳答案

    [dcl.fct.def.coroutine]p3 :

    The promise type of a coroutine is std::coroutine_traits<R, P1, ..., Pn>::promise_type, where R is the return type of the function, and P1 ... Pn are the sequence of types of the function parameters, preceded by the type of the implicit object parameter (12.4.1) if the coroutine is a non-static member function.



    在您的示例中,隐式对象参数是一个常量引用,因此在关闭对象被销毁后恢复执行时,该引用将悬空。

    然而,在成员函数执行期间对象被销毁的情况下,这本身确实很好,除了标准本身在 [basic] 中暗示了这一点之外。 :

    Before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that represents the address of the storage location where the object will be or was located may be used but only in limited ways. [...]

    void B::mutate() {
      new (this) D2;    // reuses storage --- ends the lifetime of *this
      f();              // undefined behavior
      ... = this;       // OK, this points to valid memory
    }
    


    (注意:上面的 UB 是因为隐式 this 没有被清洗,仍然是指隐式对象参数。)

    因此,您的示例似乎定义明确,条件是恢复执行不属于与原始调用相同的规则。请注意,对闭包对象的引用可能是悬空的,但在暂停和恢复之间不会以任何方式访问它。

    关于c++ - 恢复生命周期已经结束的对象的成员函数协程是UB吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60637770/

    相关文章:

    C++ 段错误

    .net - 需要使用 .NET 支持复制 IDispatch*;不知道类(class)名称

    c++ - C++20 中的 std::launder 用例

    c++ - 为什么不允许非静态成员的地址作为模板非类型参数?

    c++ - Qt 6.4.3 QMediaPlayer::资源错误 "Could not open file"

    c++ - 返回一个本地指针

    c++ - 是什么让 i = i++ + 1;在 C++17 中合法吗?

    c++ - 如何为 C++ 重载解析和 SFINAE 编写正/负测试?

    在 gcc 9.3 中编译但不能在 gcc 10.2 中编译的 C++ 代码

    c++ - 当我创建我的助手类时,我是否过度设计了?