[Effective C++] 17. new로 생성한 객체를 스마트 포인터에 저장하는 코드는 별도의 한 문장으로 만들자
728x90
반응형
우리가 자원관리 객체를 사용하고 있다고 하더라도 잘못 사용하고 있다면 자원이 누수될 가능성이 있다.
어떻게 사용하면 자원을 더욱 안전하게 사용할 수 있는지 알아보자.
자원의 누수가 발생할 수 있는 코드
void processWidget(std::shared_ptr<Widget>(new Widget), priority());
processWidget 호출 코드를 만들기 전에 컴파일러는 아래 세 가지 연산을 위한 코드를 만들어야 한다.
- new Widget 표현식을 실행하는 부분
- shared_ptr 생성자를 호출하는 부분
- priority()를 호출하는 부분
그리고 C++에서 이 연산의 순서는 컴파일러마다 다르다.
물론 new Widget은 shared_prt생성자의 인자로 넘어가기 때문에 shared_ptr보다는 전에 호출되어야 하겠지만 priority의 호출은 어디서나 불릴 수 있다.
만약에 new Widget -> priority() -> shared_ptr 순으로 호출되고 priority()에서 예외가 발생했다면 new Widget으로 만들어졌던 포인터는 유실될 수 있다.
따라서 자원이 생성되는 시점과 자원이 자원관리 객체로 넘어가는 시점 사이에 예외가 끼어든다면 자원은 유실될 수도 있다는 말이다.
해결 방법
위 문제의 해결법은 간단한데, Widget을 생성해서 스마트 포인터에 저장하는 코드를 별도의 문장으로 만들고 그 스마트 포인터를 processWidget에 넘기면 된다.
std::tr1::shared_ptr<Widget> pw(new Widget);
processWidget(pw, priority());
한 문장 안에 있는 연산들보다 문장과 문장 사이에 있는 연산들이 컴파일러의 재조정을 받을 여지가 적기 때문에 위의 코드는 자원 누출 가능성이 없다.
요약
- new로 생성한 객체를 스마트 포인터로 넣는 코드는 별도의 한 문장으로 만들자. 이것이 안되어 있으면, 예외가 발생될 때 디버깅하기 힘든 자원 누출이 될 수 있다.
728x90
반응형
'Books > Effective C++' 카테고리의 다른 글
[Effective C++] 19. 클래스 설계는 타입 설계와 똑같이 취급하자 (0) | 2022.05.29 |
---|---|
[Effective C++] 18. 인터페이스 설계는 제대로 쓰기엔 쉽게, 엉터리로 쓰기엔 어렵게 하자 (0) | 2022.05.29 |
[Effective C++] 16. new 및 delete를 사용할 때는 형태를 반드시 맞추자 (0) | 2022.05.25 |
[Effective C++] 15. 자원 관리 클래스에서 관리되는 자원은 외부에서 접근할 수 있도록 하자 (0) | 2022.05.22 |
[Effective C++] 14. 자원 관리 클래스의 복사 동작에 대해 진지하게 고찰하자 (0) | 2022.05.22 |
댓글
이 글 공유하기
다른 글
-
[Effective C++] 19. 클래스 설계는 타입 설계와 똑같이 취급하자
[Effective C++] 19. 클래스 설계는 타입 설계와 똑같이 취급하자
2022.05.29 -
[Effective C++] 18. 인터페이스 설계는 제대로 쓰기엔 쉽게, 엉터리로 쓰기엔 어렵게 하자
[Effective C++] 18. 인터페이스 설계는 제대로 쓰기엔 쉽게, 엉터리로 쓰기엔 어렵게 하자
2022.05.29 -
[Effective C++] 16. new 및 delete를 사용할 때는 형태를 반드시 맞추자
[Effective C++] 16. new 및 delete를 사용할 때는 형태를 반드시 맞추자
2022.05.25 -
[Effective C++] 15. 자원 관리 클래스에서 관리되는 자원은 외부에서 접근할 수 있도록 하자
[Effective C++] 15. 자원 관리 클래스에서 관리되는 자원은 외부에서 접근할 수 있도록 하자
2022.05.22