아래 코드를 보자

 

1
2
3
4
5
6
7
int priority(); 
 
void processWidget( std::tr1::shared_ptr<Widget> pw, int priority ); 
 
... 
 
processWidget(new Widget, priority()); //컴파일 에러

 

이 코드가 컴파일 에러가 나는 이유는 std::tr1::shared_ptr 의 생성자는 explicit 되어있기때문에 new Widget 같은 표현식이 올수 없다.

 

processWidget(std::tr1::shared_ptr<Widget>(new Widget), priority());

 

위의 코드는 컴파일에 문제가 없다.

하지만, 스마트 포인터로 받은 자원을 흘릴 가능성이 있는 함수다.

 

왜 그럴까?

C++함수는 함수를 호출할때 함수로 들어오는 인자의 평가 순서를 지니게 된다.

첫번째 인자는 (new Widget) 과 std::tr1::shared_ptr의 생성자 호출부분으로 나뉜다.

두번째 인자는 함수포인터로 함수의 호출문이 있다.

 

우선 위의 함수가 호출될때 컴파일러는 세가지 연산을 위한 코드를 만든다.

 

1. priority를 호출한다.

2. new widget 을 실행한다.

3. std::tr1::shared_ptr 생성자를 호출합니다.

 

이 연산이 실행되는 순서는 컴파일러 제작사마다 다르다.  

 

우선  std::tr1::shared_ptr은 new widget 이 실행되야지만, 실행되는 순서이다. 그렇기 때문에 순서가 변하지는 않지만, priority는 처음 호출될수도 있고, 두번째, 세번째도 호출될 수도 있습니다.

 

이때 2번과 3번 중간에 priority 함수가 호출되서 예외가 발생했다면, 자원을 막아줄줄 알고 준비한 std::tr1::shared_ptr에 저장되기도 전에 예외가 발생합니다.

 

위와같은 문제를 해결하기 위해서는?

 

 

어찌되었든 가장중요한 건!!

ProcessWidget 함수가 호출되기전에 Widget을 생성해서 스마트 포인터에 저장하는 코드를 별도의 한문장으로 하나 만들고, 그 스마트포인터를 넘기는 것입니다.

 

std::tr1::shared_ptr<Widget> pw( new Widget );

processWidget( pw, priority() );

 

이것 만은 잊지 말자!

◆ new로 생성한 객체를 스마트 포인터로 넣는 코드는 별도의 한 문장으로 만듭시다. 이것이 안되어 있으면, 예외가 발생될 때 디버깅하기 힘든 자원 누출이 초래될 수 있습니다.


+ Recent posts