스토리텔링 개발자

[Effective C++] 17. 스마트 포인터 생성 시 예외 문제 본문

개발/Effective C++

[Effective C++] 17. 스마트 포인터 생성 시 예외 문제

김디트 2024. 6. 10. 11:26
728x90

항목 17. new로 생성한 객체를 스마트 포인터에 저장하는 코드는 별도의 한 문장으로 맞추자

 

 

 

매개변수 평가
  • 다음 코드는 자원을 흘릴 가능성이 있다.
  • void processWidget(shared_ptr<Widget> pw, int priority);
    ...
    processWidget(shared_ptr<Widget>(new Widget), priority());
  • 컴파일러는 호출 코드를 만들기 전, 매개변수로 넘겨지는 인자를 평가한다.
    • 두 번째 인자(priority 함수)는 호출문 뿐이다.
    • 첫 번째 인자(shared_ptr<Widget>(new Widget)은 두 부분으로 나뉘어져 있다.
      1. "new Widget" 표현식을 실행하는 부분
      2. shared_ptr 생성자를 호출하는 부분
    • 그러므로 컴파일러는 다음 세 가지 연산을 위한 코드를 생성한다.
      1. priority를 호출한다.
      2. "new Widget"을 실행한다.
      3. shared_ptr 생성자를 호출한다.
  • C++ 컴파일러는 다른 언어(C# 또는 자바)와 달리 매개변수의 평가 순서가 자유롭다.
    • 즉, 컴파일러마다 매개 변수 평가 순서가 다를 수 있다.

 

 

 

문제가 되는 매개변수 평가 순서 예시
  • new Widget 표현식이 shared_ptr 생성자보다 먼저 호출되는 것은 서로 연계되므로 당연하다.
  • 하지만 priority 함수의 경우 상당한 자유도가 있을 수 있다.
  • 여기서 문제가 되는 것은 priority 함수에서 예외가 발생하는 경우이다.
  • 순서 예 1.
    1. priority 함수 호출
      • 예외가 발생하더라도 메모리 누수는 없다.
    2. new Widget 실행
    3. tr1::shared_ptr 생성자 호출

 

  • 순서 예 2.
    1. new Widget 실행
    2. priority 함수 호출
      • 예외 발생시 Widget 자원이 누수된다.
    3. tr1::shared_ptr 생성자 호출
  • 즉, 자원이 생성되는 시점(new Widget)과 그 자원이 자원 관리 객체로 넘어가는 시점 사이에 예외가 끼어들 수 있는 여지가 있다.

 

 

 

해결
  • new로 생성한 객체를 스마트 포인터로 넣는 코드를 별도의 한 문장으로 만들자
  • shared_ptr<Widget> pw(new Widget);
    processWidget(pw, priority());

 

728x90
Comments