2021 시작

Widget이라는 클래스가 있고 우선순위를 반환하는 priority() 라는 함수와 shared_ptr객체와 우선순위를 매개변수로 받는 processWidget()함수가 있다고 하자(아래 코드를 보자)

class Widget
{
public:
	
};

int priority(){return 1;};

void processWidget(shared_ptr<Widget> pw,int priority)
{
	cout<<"Call Func -> processWidget"<<endl;
} 

int _tmain(int argc, char** argv) {
	
	processWidget((new Widget),priority());		//error!
	
	return 0;
}

 

위의 코드를 보면 processWidget변수에 (new Widget)으로 값을 넘기려 하고 있다. 하지만  이것은 불가능하다.

 이유는 shared_ptr의 생성자는 explicit로 선언되어 묵시적으로 Widget으로 형변환이 되지 않기 때문이다.

대신 다음처럼은 쓸 수 있다.

int _tmain()
{
	processWidget(shared_ptr<Widget>(new Widget), priority());	
}

 

값을 넘길 때 아얘 shared_ptr<Widget>로 넘겨주는 거다.

그러면 "보통"의 컴파일러는 다음과 같이 연산순서를 정한다.

 

1. priority() 함수 호출 후 반환

2. new Widget 표현식 실행

3. shared_ptr 생성자 호출

 

모든 컴파일러가 이런 순서로 된다면 아무런 문제가 없을 것이다.

하지만  c++컴파일러의 경우에는 제작사 마다 순서가 다를정도로 순서에 대해 상당한 자유도가 있기때문에 다음과 같이 순서가 바뀌어 실행될 수도있다.

 

1. new Widget 표현식 실행

2. priority()를 호출 후 반환

3. shared_ptr 생성자 호출

 

만약 이 순서로 연산이 되었을 때 2번에서 예외가 발생하면 1번에서 할당한 Widget이라는 자원이 누출될것이다. 그러기 때문에 이 문제를 해결하는 방법은 Widget을 할당하고 shared_ptr에 넣는 문장과 processWidget함수에 스마트포인터를 넘기는 문장을 따로 나눠놓으면 된다. 

다음 예제 코드를 보자

int _tmain()
{
	shared_ptr<Widget>pw(new Widget);	//new로 생성한 객체를 
							//스마트 포인터에 담는 코드를
							//하나의 독립적인 문장으로 만든다.
							 
	processWidget(pw, priority());	//이제는 자원 누출 걱정이없다. 
	
}

 

이것만은 잊지 말자!

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

공유하기

facebook twitter kakaoTalk kakaostory naver band
loading