4

내 동료 중 한 사람은 객체의 소멸자 호출이 시작되자 스레드 (객체 자체의 구성원)에 의해 수행 된 객체 구성원에 대한 모든 액세스가 인 것을 UB라고 주장합니다.부모 소멸자에서 부모 클래스의 다른 멤버에 액세스하는 멤버 스레드를 조인하면 정의되지 않은 동작이 발생합니까?

이것은 스레드가 객체의 다른 구성원 중 하나에 액세스하는 경우 객체의 소멸자 중에 std::thread::join을 호출하는 것이 UB임을 의미합니다.

"Object Lifetime" 아래의 최신 표준 초안을 간략하게 살펴 보았지만 결론적 인 대답을 찾지 못했습니다.

다음 코드 (on wandbox)의 정의되지 않은 동작을 나타냅니다.?이 상호 작용을 명확히하는 표준 부분은 무엇입니까?

struct A 
{ 
    atomic<bool> x{true}; 
    thread t; 

// Capturing 'this' is part of the issue. 
// The idea is that accessing 'this->x' becomes invalid as soon as '~A()' is entered. 
//   vvvv 
    A() : t([this] 
      { 
       while(x) 
       { 
        this_thread::sleep_for(chrono::milliseconds(100)); 
       } 
      }) 
    { 
    } 

    ~A() 
    { 
     x = false; 
     t.join(); 
    } 
}; 

int main() 
{ 
    A a; 
} 
+0

아무 의미가 없습니다. 그는 소멸자에서 원시 멤버 포인터를 삭제하는 것이 UB이기도하다는 것을 의미합니까? 메인 스레드에서 발생했거나 경쟁 조건과 잘못된 코드를 의미하는 소멸자를 실행하는 2 개의 스레드를 의미하기 때문입니다. 당신은 그에게 그의 믿음의 근원을 더 잘 물어 봐야합니다 :) – Arunmu

+1

"** [class.cdtor]/1 ** 비 정적 인 소멸자가있는 객체의 경우, 객체의 비 정적 멤버 또는 기본 클래스를 참조하십시오. * 소멸자가 실행을 끝내면 정의되지 않은 동작이 발생합니다. " 강조. 이것은 소멸자가 실행을 끝내기 전에 멤버에 액세스하는 것이 좋다고 암시하는 것으로 보입니다. –

+2

그것에 대해 생각해보십시오. _ 전형적으로 소멸자에서 수행하는 작업은 아직 살아있는 구성원에 따라 다릅니다. 소멸자는 작업 할 수있는 어떤 인자도 가지고 있지 않습니다. 유일한 것은'this'이므로'this->'는 사용 가능한 객체를 더 잘 참조합니다. – MSalters

답변

6

이것은 정의되지 않은 동작입니다. 우리는 [class.dtor]에서/8을 보면 우리가 신체 내에서 할당 된 자동 객체 소멸자의 시체를 실행하고 파괴 후

이, 클래스 X에 대한 소멸자는 X의 직접 비 변형에 대한 소멸자를 호출 비 정적 데이터 멤버 인 X의 직접 기본 클래스의 소멸자이며 X가 가장 파생 클래스 (12.6.2)의 유형 인 경우 소멸자는 X의 가상 기본 클래스에 대한 소멸자를 호출합니다.

이는 소멸자의 본문이 실행 된 후에 클래스의 비 정적 구성원이 파괴된다는 것을 나타냅니다. 즉, 모든 멤버가 소멸자에서 살아 있고 x을 조작하고 join을 호출하면 정상적인 멤버 함수에서와 동일하게 동작합니다. 유일한 차이점은 소멸자의 몸이 달린 후 구성원 자체가 파괴된다는 것입니다.

3

이 질문에 태그가 붙어 있기 때문에 N3337 사용하기 C++ 11.

그것은이 소멸자 실행 중 클래스 멤버에 액세스하는 정의되지 않은 것을하지 않는 것 :

§12.7 [class.cdtor]/1

이 아닌 사소한 소멸자와 개체에 대한

, 소멸자 후 개체의 비 정적 멤버 또는 기본 클래스 이 완료되면 정의되지 않은 동작이 발생합니다.

이 §12.4 [class.dtor] 소멸자는 객체에 대해 호출되면/15

는 개체가 더 이상 존재하지 언급하지 비록

다음은 객체를 논의 할 때 12.7에 명시 적으로 연결됩니다.

§3.8 [기본.객체의 수명 전에 삶]/5

시작하지만, 한 개체가 개체의 수명이 종료 된 후 저장하기 전에 38 또는 를 할당 된 차지할 저장 후하는 을 점유 된 오브젝트가 재사용되거나 해제 될 때, 오브젝트가 위치하거나 저장된 위치 인 을 가리키는 모든 포인터는 이 사용되지만 제한된 f}으로 만 사용될 수 있습니다. 구성중인 개체 또는 파괴에 대해서는 12.7을 참조하십시오.