수명이 종료 된 객체의 멤버 함수 코 루틴을 재개하는 것이 UB입니까?


9

이 질문은이 의견에서 비롯됩니다 : C ++ 20 코 루틴에 대한 Lambda 수명 설명

이 예와 관련하여 :

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

따라서 반환 된 코 루틴을 실행하면 fooUB가 발생 하는지 여부가 문제입니다 .

"객체의 수명이 끝난 후"멤버 함수 "호출"은 UB입니다. http://eel.is/c++draft/basic.life#6.2

... 물체가 위치하거나 위치 할 저장 위치의 주소를 나타내는 포인터는 제한적으로 만 사용될 수 있습니다. [...] 다음과 같은 경우 프로그램에 정의되지 않은 동작이 있습니다.

[...]

- 포인터가 액세스 할 수있는 비 - 정적 데이터 부재를 사용하거나되는 물체의 비 정적 멤버 함수를 호출 하거나

그러나이 예에서는

  • ()람다의 수명은 여전히 ​​유효하지만 람다 의 연산자가 호출됩니다.
  • 그런 다음 일시 중지됩니다.
  • 람다는 파괴되고
  • 그런 다음 멤버 함수 (operator ())가 나중에 어느 시점에서 다시 시작됩니다.

이 재개는 정의되지 않은 동작으로 간주됩니까?


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
}

(NB : 위의 UB는 암시 적이 this세탁되지 않고 여전히 암시 적 객체 매개 변수를 참조하기 때문입니다.)

따라서 실행 재개가 원래 호출과 동일한 규칙에 속하지 않는다는 아이디어에 따라 예제가 잘 정의 된 것처럼 보입니다. 클로저 객체에 대한 참조가 매달려있을 수 있지만, 일시 중지와 재개 사이에는 어떤 식 으로든 액세스 할 수 없습니다.


마지막에 "재개 및 완료"를 의미합니까?
Davis Herring

@DavisHerring 아니오, 구체적으로 그 "외부"시간 범위 내에서 참조가 실제 객체를 필요로하는 새로운 참조 등에 할당 될 수 있는지 명확하지 않은 경우를 의미합니다. 참조가 숨겨진 방식으로 액세스되지 않는다는 사실은 이것이 UB가 아닌 것이 중요합니다.
Columbo

그러나 재개 될 때까지 매달린 참조 만 남겨 두는 것만으로는 충분하지 않습니다. 남은 생애 동안, 람다 몸에 ( 예 : 람다 몸에) 영원히 남겨 두어야합니다 . 아마도 "현탁 및 완료"여야합니다.
Davis Herring

@DavisHerring이 예에서는 다른 구간이 안전하다는 것을 알고 있기 때문에 그 구간에 대해 구체적으로 언급했습니다.
Columbo

확실한; 나는 단지 혼란스러운 표현을 발견한다. 다른 사람은 없을 것입니다.
Davis Herring
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.