存続期間が終了したオブジェクトのメンバー関数コルーチンを再開するのはUBですか?


9

この質問は、このコメントから生じています:C ++ 20コルーチンのラムダ寿命の説明

この例について:

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

...オブジェクトが配置される、または配置された保管場所のアドレスを表すポインターは、限られた方法でのみ使用できます。[...]次の場合、プログラムは未定義の動作をします。

[...]

-ポインタは非静的データメンバにアクセスしたりするために使用されるオブジェクトの非静的メンバ関数を呼び出し、または

ただし、この例では:

  • ()ラムダの有効期間中にラムダの演算子が呼び出されます
  • その後、中断され、
  • 次にラムダが破壊され、
  • その後、メンバー関数(演算子())はある時点で再開されます。

この再開は未定義の動作と見なされますか?


2
たぶん、次の答えは関連性があるstackoverflow.com/a/60495359/12345656それはかなり違うようだが、それはまた、実行中のメンバ関数についてですthisポインタが無効化されます。コメントでの議論も考慮してください。
n314159

回答:


2

[dcl.fct.def.coroutine] p3

コルーチンのプロミス型std::coroutine_traits<R, P1, ..., Pn>::promise_typeであり、Rは関数の戻り型で P1 ... Pnあり、関数パラメータの型のシーケンスであり 、コルーチンが非静的の場合は、暗黙のオブジェクトパラメータの型(12.4.1)が前に付きます。メンバー関数。

暗黙のオブジェクトパラメータは、例ではconst参照であるため、クロージャオブジェクトが破棄された後で実行が再開されると、その参照はぶら下がります。

ただし、メンバー関数の実行中にオブジェクトが破棄されることに注意すると、これは実際にそれ自体で問題なく、標準自体がこれを[basic]で示唆しています

オブジェクトの存続期間が開始する前、ただしオブジェクトが占有するストレージが割り当てられた後、またはオブジェクトの存続期間が終了してオブジェクトが占有したストレージが再利用または解放される前に、アドレスを表すポインタオブジェクトが配置される、または配置された保管場所を使用できますが、使用方法は限定されています。[...]

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、暗黙的オブジェクトがロンダーされず、暗黙的オブジェクトパラメータを参照するためです。)

そのため、実行の再開が元の呼び出しと同じ規則に該当しないという考えを条件として、例は明確に定義されているように見えます。クロージャーオブジェクトへの参照はぶら下がっている可能性がありますが、一時停止と再開の間ではアクセスされないことに注意してください。


最後に「再開と完了」という意味ですか?
Davis Herring

@DavisHerringいいえ、私は具体的には、その「外部」の時間枠内で、参照が実際のオブジェクトを必要とする新しい参照などに割り当てられるかどうかが明確でないことを意味しました。参照が隠された方法でアクセスされないという事実は、これがUBではないために重要です
コロンボ

しかし、ダングリングリファレンスを再開するまでそのままにしておくだけでは十分ではありません。あなたはそれを(例えば、ラムダの体の中で)永遠に放っておかなければなりません— それが完了するまでであるその寿命の残りの間。ですから多分それは「一時停止と完了」であるべきです。
Davis Herring

@DavisHerringこの例では、他の1つが安全であることがわかっているため、その間隔について具体的に説明しました。
コロンボ

承知しました; 言葉が混乱するだけです。多分誰もしません。
Davis Herring
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.