2012-01-30 5 views
6

this question에 답하고 표준 논문에서 만족할만한 대답을 찾지 못한 후, 나는 궁금해하기 시작했다. 표준에서는 다음과 같은 내용을 설명합니다. 한 변수의 초기화 :블록 스코어 정적 또는 스레드 저장 기간 변수의 실패 초기화가 무엇입니까?

§6.7 [stmt.dcl] p4

[...]가 그러한 변수가 처음으로 제어 선언 통과 초기화된다; 이러한 변수는 초기화가 완료되면 초기화됩니다.. 예외를 throw하여 초기화가 끝나면 초기화가 완료되지 않으므로 다음에 컨트롤이 선언에 들어올 때 다시 시도됩니다.

은 (, 신호가 몇 가지 이름을 longjmp(), THEAD 종료) 예외를 던지는 것보다 아무것도에 의해 실패하면 초기화가 시도하는 발생할 수 있습니다 무엇인지 전혀 대한 언급이 없다.

표준에서 어떤 것도 간과 했습니까? 초기화, 선언 및 예외 조항을 반복적으로 살펴 보았고 CWG defects table of content을 "정적"이라는 빠른 검색과상의했지만 관련 항목을 찾을 수 없었습니다.

표준의 규격 외의 (및 이와 같은 결함)이 있습니까?

+1

C++은 신호와 관련하여 _anything_을 정의합니까? 아니면'longjmp'? 스레드 이탈은 상황을 바꿀 수 있습니다. –

+0

표준에 따라 적절히 지정되지 않았다는 구체적인 시나리오가 있습니까? –

+0

@Kerrek : 연결된 질문입니다. : P – Xeo

답변

2

C++ 사양은 C++ 사양에 포함 된 항목 만 정의 할 수 있습니다. C++ 사양은 정의한 가상 컴퓨터의 동작을 정의합니다. 그리고 어떤 일이 일어날 수 있다고 정의하지 않는다면, C++의 동작은 말할 수없는 무언가가 일어날 수 있다는 것을 분명히 정의하지 않습니다.

C++ 사양에 따르면 스레드는 주 기능에서 복귀하고 주 기능을 통해 예외를 던지고 직접 프로세스 종료 (std::terminate 또는 이와 유사한 기능과 같이)하는 세 가지 방법으로 종료 할 수 있습니다. 즉, C++ 스레드 은 다른 방법으로는을 종료 할 수 없습니다. 표준 C++에는 ExitThread 함수가 없습니다. 마찬가지로 std::thread은 외부 또는 내부에서 스레드를 죽일 수 없습니다.

따라서 C++에서 발생할 수없는 문제는 정의되지 않은 것입니다. 나는 그것이 "정의되지 않은 행동"이 아닐 것이라고 생각한다. C++ 11이 실제로 스레드 상호 작용이 어떻게 작동하는지 알기 전에 스레딩 (threading)이 있었던 것은 어둡습니다.

"신호"는 무엇이든지간에 마찬가지입니다. C++ 사양은 함수가 종료 될 수 있다고 말하지 않습니다. 여기는 용 이예요.

longjmp의 경우는 동작이 longjmp입니다. longjmp을 사용하여 함수를 종료하면 throwcatch을 사용한 것처럼 함수가 완료되지 않습니다. 그리고 C++에서 객체는 생성자가 완성되었을 때만 생성됩니다. 따라서 개체의 초기화가 완료되지 않고 초기화되지 않은 것입니다.

나는 C++ (11) 당신이 얻을 때 늘어나는만큼, throw/catchlongjmp/setjmp와 동일시 할 수있는 제안 강하게 않습니다 (longjmp의 행동 C++ 참조)하지만, ISO C 규격이없는 정의되지 않은 동작 :

§18.10 [support.runtime] p4: 

함수 서명하는 longjmp는 (되는 jmp_buf jbuf, INT 발)이 국제 표준에보다 제한된 동작을 가지고있다. setjmp와 longjmp를 catch와 throw로 대체하면 모든 자동 객체에 대해 사소한 소멸자를 호출하지 않으면 setjmp/longjmp 호출 쌍이 정의되지 않은 동작을합니다.

나는 이것이 구체적으로 밝혀지지 않았다고 생각하지 않습니다. 멋있고 깔끔하게 배치되지는 않지만 모든 조각이 있습니다.

0

텍스트에 특정 사례가 언급되어 있다고해서 누락되어 다른 사람이 다를 수 있음을 의미하지는 않습니다. 초기화가 완료되지 않게하는 다른 방법이있는 경우, 구현은 다음 실행시에 재 시도해야합니다.

Nicol의 대답은 대부분 정확하다고 생각하지만, 사소하지 않은 생성자는 의미없는 소멸자가 아닙니다. 따라서 longjmp은 재 시도해야하는 초기화를 인터럽트 할 수 있습니다. 이것은 다중 스레드 환경에서만 까다 롭습니다. 스레드가 초기화를 가장 먼저 수행하려고 경쟁하는 것을 막기 위해 뮤텍스가 필요합니다. phantom 뮤텍스 객체는 초기화 된 객체가 없어도 중요하지 않은 소멸자가 필요합니다. 가능한 결과는 교착 상태입니다. 이것은 아마도 DR을위한 좋은 자료 일 것입니다.

+0

표준이 하나의 사례 만 나열하는 것은 아니며, 해당 사례 *에 대해서만 재 시도 *를 지정합니다. "실패하면 다음 번에 다시 시도하십시오"라는 말은하지 않습니다. 특히 "*를 던지면서 실패한 경우 다음 번에 다시 시도하십시오"라고 표시됩니다. – Xeo

+0

@Xeo : 전혀 아닙니다. 초기화가 완료되지 않은 경우, 처음에 초기화가 아닙니다. 재 시도 *가 처음 *입니다. 앞의 텍스트가 이미 암시하고있는 것은 이미 "초기화가 완료되지 않았기 때문에 ** 다시 시도 될 것입니다 ..."라는 언어에 의해 밝혀졌습니다. – Potatoswatter

+0

* 전에는 * 예외가 * 언급되기 때문에 그럴 수 없습니다. 두 부분을 분리 할 수는 없습니다. 어쨌든, 나는 이것이 최소한의 설명을위한 좋은 후보라고 생각한다. Btw, 뮤텍스 문제에서 138 페이지의이 발 참고 사항이 적용될 수 있다고 생각합니다. "구현은 이니셜 라이저를 실행하는 데 교착 상태가 발생해서는 안됩니다." – Xeo