2014-02-17 2 views
3

최근에 나는 noexcept 예외 사양에서 simple question이 될 것이라고 생각했던 답변에 노력했습니다. 결과적으로 나는 noexcept의 근본적인 이해가 잘못되었다는 것을 알게되었습니다.noexcept 및 안정성 보장

오해를 바로 잡기 위해 the current draft standard을 읽는 동안 here에 대한 답변이없는 noexcept에 대해 몇 가지 질문을했습니다.

  1. noexcept은 안전 보장으로 간주해야합니까? 호출 할 때 함수가 throw되지 않고 상태가 손상되지 않습니까?
  2. (1)이 거짓이라고 가정합니다. 휴대 전화 FailFast으로 noexcept을 사용하여 저장된 상태가 손상되지 않도록 정리하지 않고 응용 프로그램을 종료하는 것이 맞습니까? (2)에

명확한 설명 : 목적은뿐만 아니라 그 안에 긴장을 풀기 방지하기 위해 noexcept에서 스택까지 더 소멸자 호출을 방지하는 것입니다. 이것은 완벽한 RAII 환경이고 스택을 소멸시키는 사람이 전역 상태를 지속성으로 플러시하여 손상시킬 수 있다는 가정에 기반합니다. 미리 형성되지 않은 방법 풀기의

예 :

#include <iostream> 
#include <exception> 

namespace{ 
    struct foo{ 
     void change_state() noexcept 
     { 
      // change state and fail 
      throw std::exception(); 
     } 
     ~foo(){ 
      std::cout << "Destructor called, saved state corrupted!" <<std::endl; 
     } 
    }; 
} 


int main(){ 
    ::std::set_terminate([](){ 
     std::cout<< "Terminate called" <<std::endl; 
    }); 

    foo f; 
    f.change_state(); 
    return 0; 
} 

Working example of noexcept

+0

내가 '예외 없음'을 이해함에 따라 :이 문제가 발생하더라도 나는 그것에 대해 알고 싶지 않습니다. 그래서 "안전"또는 "정확함"을 위해 실제로 작동하지 않습니다. 예외가 발생하지 않도록하여 작동하므로 프로그램이 종료되지 않습니다. – user2485710

+1

예외가'noexcept'로 표시된 함수의 가장 바깥 쪽 블록에 도달하면'std :: terminate'가 호출됩니다. 예외를 전혀 억제하지는 않습니다. 그것은 예외가 던져 질 수없는 장벽을 제공합니다. – Mgetz

+0

전에 썼던 것은 _runtime_에 관한 것이고, 'noexcept'는 컴파일 타임에 작동합니다. 그래서 컴파일러에 대한 힌트이고 컴파일러는 프로그램을 평가하고 무언가가 던져 질 가능성이 있다면 , 당신은'noexcept' 연산자가 _compile time_에 실패하기 때문에 _runtime_ 전에 이것을 수정할 기회가 있습니다. 어떤면에서'형질 형 '처럼 작동합니다. 컴파일러가 경고하지 않으면,'true'로 평가되어야하는 프로퍼티를 정의합니다. 테스트가 _runtime_에 당신의 타입이 '형질'조건. 'noexcept'도 마찬가지입니다. – user2485710

답변

2
  1. 예. 함수는 throw 여부에 관계없이 상태, 기간을 손상시키지 않아야합니다. 예외가 throw되도록 이 필요하다는 사실은 중요하지 않습니다. [물론, 프로그램을 중단시키지 않을 것이라는 보장은 없습니다. 그러나 그런 종류의 행동은 문서화되어야합니다. ;-)]
  2. Mu. 함수가 noexcept을 던질 것으로 예상되면 던지기를해서는 안됩니다. 그냥 std::terminate (또는 std::abort)으로 전화해야합니다.
+0

나는 그 실패가 명시 적이어야하고'noexcept'의 행동에 의존하지 않는다는 것을 이해하고 있습니다. 'noexcept'라고 표시된 함수가 던져주는 함수를 호출 할 때 나는 이론적으로 파고 있다고 가정합니다. 예외를 잡아서'std :: terminate'를 호출합니까? – Mgetz

+1

어 ... 외부 함수가 예외를 포착하고 처리하는 것이 유용 할 경우 물론 그렇게해야합니다. 그 후, 클래스 불변량을 유지하는 것이 어렵지 않다는 것을 증명하기 위해 아마도'terminate '를 호출해야합니다. '던지다 '는 의미 중 하나는 "괜찮아. 괜찮아."라는 뜻입니다. 그렇게 말하면,'throw '가'noexcept'에서 벗어난 스크린 공간의 1 인치라면 그렇게 중요하지 않습니다. – Sneftel

1

noexcept 많이 해제 할 수없는 assert 처럼, 계약 보증이다. noexcept 으로 표시된 기능이 예외를 통해 종료하려고하면 사후 조건이 위반되었으며 아무 것도 계산할 수 없습니다. 프로그램은 종료됩니다. 따라서, 1은 거짓이다.

2는 더 어렵습니다. 구현은 noexcept과 함께 기능을 떠날 때까지 스택을 풀 수 있습니다. 이 스택을 더 풀어주지 못하도록하는 것은 적어도 100 % 명확하지 않습니다. 응용 프로그램을 정리하지 않고 종료하려는 경우 abort()으로 전화를 걸어 을 추가 작업없이 바로 종료하도록 보장합니다. 또한 은 다른 기능의 일부 보조 효과를 고려하여 이 아닌 정확히 무슨 일이 일어나는지 독자에게 알려줍니다.

+0

그래서이 특별한 경우에 안전하지 않은 ('noexcept'가 아닌) 모든 호출을'catch'로 감쌀 것인가? 'std :: abort'를 호출하여 더 이상의 풀기를 방지 할 수 있습니까? (나는'noexcept' 함수 내에서 풀면 저장 상태가 손상되지 않는다고 가정하고있다.) – Mgetz

+0

@Mgetz 일반적으로 나는 안전하지 않은 호출을하지 않을 것이다 :-). 그렇지 않으면, 나는 그들을 삼키고 싶을 때만 그들을 감쌀 것이다. (예를 들어 스택 해체 중에 호출 될 수있는 소멸자의 경우가 많다.) –

+0

내 질문은 분명하지 않다 ... 의도는 소멸자가'noexcept'보다 스택을 더 멀리 호출하는 것을 방지하기위한 것입니다. 그러나 내가 당신을 이해한다면, 세계적인 구원 국가가 손상 될 수있는 경우, '예외가없는'문맥에서처럼 행동하고, 즉시 필요하다면 '중단'하는 것이 더 낫다는 것입니다. – Mgetz