반응형
0. 요약
- new로 생성한 객체를 스마트포인터에 저장하는 코드를 별도의 한 문장으로 만들자
- shared_ptr
pw(new xxx);
- shared_ptr
- 이유
- new 실행과 해당 자원을 스마트포인터 생성자로 전달하는 사이에 예외 발생시 자원 누수 발생!
1. 문제 사항
- 가정
- 처리 우선 순위를 알려주는 함수 존재
- 동적 할당한 Widget 객체에 대해 어떤 우선순위에 따라 처리를 적요하는 함수 존재
int priority();
void processWidget(std::shared_ptr<Widget> pw, int priority);
// processWidget을 사용
processWidget(new Widget, proiority());
- 위의 processWidget() 함수가 동작할까?
- shared_ptr의 생성자는 explicit로 선언되어 있음
- new Widget으로 만들어진 포인터가 shared_ptr 타입으로 암시적 변환이 되지 않음!
- 아래와 같이 명시적으로 생성 후 호출하도록 변경
processWidget(std::shared_ptr<Widget>(new Widget), priority());
- 하지만 위의 문장은 자원이 누수될 가능성이 존재!
- 위의 한 문장을 수행전 매개 변수 인자를 평가하는 순서 가짐
- 본 예시에서는 3가지 단계를 거침
- "new Widget" 을 실행 => shared_ptr 생성자를 호출 => priority() 함수 호출
- 문제는 3개의 단계의 순서가 컴파일러 마다 다름!
- 만약 호출 순서가 아래와 같고, priority 에서 예외가 발생했다면?
- "new Widget" 실행
- priority() 실행
- shared_ptr 생성자 호출
- new Widget으로 할당된 메모리가 해제되지 않아 누수 발생!
2. 해결 방법
- Widget를 생성해서 RAII에 저장하는 코드를 별도 한 문장으로 만들자!
- 그리고, 나머지 문장을 실행하자!
std::shared_ptr<Widget> pw(new Widget);
processWidget(pw, priority());
참고
- Effective C++
반응형
'C++ > Effective C++' 카테고리의 다른 글
[Effective C++] 19. 클래스 설계는 타입 설계와 똑같이 취급하자 (0) | 2021.03.15 |
---|---|
[Effective C++] 18. 인터페이스 설계는 제대로 쓰기엔 쉽게, 엉터리로 쓰기엔 어렵게 하자 (0) | 2021.03.15 |
[Effective C++] 16. new 및 delete를 사용할 때는 형태를 반드시 맞추자 (0) | 2021.03.15 |
[Effective C++] 15. 자원 관리 클래스에서 관리되는 자원은 외부에서 접근할 수 있도록 하자 (0) | 2021.03.15 |
[Effective C++] 14. 자원 관리 클래스의 복사 동작에 대해 진지하게 고찰하자. (0) | 2021.03.15 |