2016년 3월 20일 일요일

[Effective C++] 항목 17 : new로 생성한 객체를 스마트 포인터에 저장하는 코드는 별도의 한 문장으로 만들자.

- 처리 우선순위를 알려주는 함수와 동적으로 할당한 객체에 대해 우선순위에 따른 처리를 적용하는 함수가 있습니다.
  동적으로 할당 되는 Customer는 tr1::shared_ptr을 이용하여 사용하도록 만들었습니다.
?
1
2
3
4
5
6
7
8
9
// 처리 우선순위를 알려주는 함수
int priority();    
// 우선순위에 따라 처리를 적용하는 함수
void processCustomer( std::tr1::shared_ptr<costomer> pc, int priority);
{
    processCustomer( std::tr1::shared_ptr<costomer>(new Customer), priority() );
}

- 위 코드는 컴파일은 잘 되지만, 자원을 흘릴 가능성이 있습니다.

- 컴파일러는 processCustomer 호출 코드를 만들기 전에 우선 이 함수의 매개변수로 넘겨지는 인자를 평가하는 순서를 밟습니다.
  위 코드에서는 컴파일러가 processCustomer 함수 호출이 이루어 지기 전에 세 가지 연산을 위한 코드를 컴파일러가 만들게 됩니다.

① priority를 호출합니다.
② new Customer 를 실행합니다.
③ tr1::shared_ptr 생성자를 호출 합니다.

- 그런데, 여기서 각각의 연산이 실행되는 순서는 컴파일러 제작사마다 다르다는게 문제입니다.

① new Customer 를 실행합니다.
② priority를 호출합니다.
③ tr1::shared_ptr 생성자를 호출 합니다.

- 위의 순서대로 호출 될때, priority 함수에서 예외가 발생하면, shared_ptr에 저장 되기도 전에 발생했기 때문에,  
  Customer는 포인터가 유실되고, 자원 누출이 발생하게 됩니다. 

[ 개선 ]
?
1
2
3
4
    std::tr1::shared_ptr<customer> pc(new Customer);
    processCustomer( pc , priority() );
</customer>

- Customer를 생성하여 스마트 포인터에 저장하는 코드는 별도의 문장 하나로 만들고,
  그 스마트 포인터를 processCustomer에 넘기는 것입니다.
  그러면, 컴파일러의 재조정을 받을 여지가 적기 때문에 자원 누출 가능성이 없습니다.

* new로 생성한 객체를 스마트 포인터로 넣는 코드는 별도의 한 문장으로 만듭시다.

  이것이 안 되어 있으면, 예외가 발생될 때 디버깅하기 힘든 자원 누출이 초래될 수 있습니다.

댓글 없음:

댓글 쓰기

[Effective C++] 항목 30 : 인라인 함수는 미주알고주알 따져서 이해해 두자.

인라인 함수를 사용하면 컴파일러가 함수 본문에 대해 문맥별 최적화를 걸기가 용이해집니다. 인라인 함수의 아이디어는  함수 호출문을 그 함수의 본문으로 바꿔치기하자는 것  남발했다가는 코드의 크기가 커질 게 뻔하다. 인라인 함수로 부풀려진 ...