2014-12-06 2 views
1

예외로 참조되는 스택 풀기 중 로컬 변수는 어떻게됩니까? 다음 코드를 고려 :로컬 변수에 대한 const 참조가있는 예외 예외

class bar; 
class my_error 
{ 
public: 
    my_error(const bar& bar) : _bar(bar) {} 
    const bar& get_bar() const { return _bar; } 

private: 
    const bar& _bar; 
} 


... 

bar some_local_object(...); 
if (!foo()) { 
    throw my_error(some_local_object); 
} 

... 

try { 
    g(); 
} catch (my_error& e) { 
    e.get_bar() 
    ... 
} 

무엇 some_local_object 어떻게됩니까? 스택을 푸는 동안 파괴해서는 안됩니까? 예제에서 제공된대로 사용하는 것이 안전합니까?

추가 질문

로 이미 대답이 코드는 정의되지 않은 동작이 발생할 것입니다. 내 두 번째 질문은 다음과 같습니다.

로컬 객체에 대한 참조를 전달할 권한이 없거나 드문 경우 bad_alloc이 발생할 수 있으므로 사본을 만들지 않아야합니다 (이것이 gcc 표준입니다. 라이브러리에 의미있는 오류 메시지가 없습니다. 즉, map.at에서 what()이 "map.at"을 반환하는 예외를 던지면 추가 정보를 전달하는 좋은 전략은 무엇입니까? 오류 메시지 생성 중에 여러 문자열을 조인해도 이론적으로 bad_alloc이 발생할 수 있습니다. 즉 :

void do_something(const key& k, ....) 
{ 
    ... 
    if (!foo(k)) { 
     std::ostringstream os; 
     os << "Key " << k << " not found"; // could throw bad_alloc 
     throw std::runtime_error(os.str()); 
    } 
    // another approcach 
    if (!foo(k)) { 
     throw key_not_found(k); // also bad, because exception could outlive k 
    } 
} 
+3

참조를 포함하는 객체를 반환 했으므로 아무런 차이가 없습니다. 따라서 안전하지 않습니다. –

답변

4

동작은 스택에 변수에 대한 참조를 반환 할 때와 동일합니다 : 당신이 그것을 사용하기 위해 도착하기 전에 개체가 파괴됩니다. 즉, 예외가 잡힐 때까지는 참조 된 객체가 파괴되고 참조에 대한 모든 액세스는 정의되지 않은 동작을 초래합니다.

표준의 관련 절은 15.2 [except.ctor] 제 1

제어 예외 핸들러로 발생되는 지점에서 통과함에

가 소멸자 이후 구성된 모든 자동 개체 호출 try 블록이 입력되었습니다. 자동 대상은 건설 완료의 역순으로 파괴됩니다.

+0

감사합니다. 이제 두 번째 질문이 있습니다. 만약 내가 로컬 객체에 대한 참조를 전달할 수 없거나, 복사본을 만들지 않아도된다. 왜냐하면 드물게 bad_alloc이 생길 수 있기 때문이다 (gcc 표준 라이브러리에는 의미있는 오류 메시지가 없다. 즉, map.at throws 예외가 what()이 "map.at"을 반환하는 경우), 추가 정보를 전달하는 좋은 전략은 무엇입니까? 오류 메시지 생성 중에 여러 문자열을 조인해도 이론적으로 bad_alloc이 발생할 수 있습니다. – Sasa

+1

분명한 방법은 여분의 정보를 위해 메모리를 할당하지 않고 던져진 예외 객체에 직접 필요한 정보를 삽입하는 것입니다. 분명히 예외 객체에 넣어야하는 양은 상당히 제한되어야합니다. "구현 양"은 예외 객체의 권장 최소 크기를 지정하지 않지만 극도의 리소스 제약 시스템에서 작업하지 않는 한 32 바이트, 즉 문자열 리터럴에 대한 포인터를 안전하게 저장할 수 있다고 기대합니다. 추가 정보를위한 설명 플러스, 적어도 3 단어 또는 24 문자. –

+0

그러나 던져진 예외에 * 필요한 정보를 어떻게 포함합니까? 로컬 객체가 아니더라도 예외가 여전히 임베드 객체보다 오래 남아있을 수 있기 때문에 객체에 대한 참조를 넣을 수 없습니다. 가능한 * 메모리 부족 조건 때문에 * 객체의 사본을 만들지 않아야합니다.나는 그것이 극히 드문 경우이지만, 그럼에도 불구하고 일부 도서관은 그것을 선호합니다. gcc로 작업 해본 결과 코드에 std :: map이 깊숙이 존재하며 존재하지 않는 key에 대해 map.at을 사용하면 실제로 쓸모없는 예외가 발생합니다. "map.at"오류 메시지는 아무 것도 말해주지 않습니다. – Sasa

3

로컬 개체는 스택 되감기 중에 파괴됩니다. 그러면 참조 번호가 이고 참조 번호가입니다. 즉, 참조가 사용되도록 예외 객체를 검사하면 정의되지 않은 동작이 발생합니다.