[c++ korea] effective modern c++ study item 19 use shared ptr for shared ownership resource...

28
Effective Modern C++ Study C++ Korea 발표자 : 윤석준

Upload: seok-joon-yun

Post on 30-Jul-2015

184 views

Category:

Software


0 download

TRANSCRIPT

Page 1: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준

Effective Modern C++ Study C++ Korea

발표자 : 윤석준

Page 2: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준
Page 3: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준
Page 4: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준
Page 5: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준

Effective Modern C++ Study C++ Korea 5

1959년 LISP의 문제를 해결하기 위해 John McCarthy가 개발

Java, C#, 대부분의 Script 언어에서 쓰이고 있음

장점 (버그를 줄이거나 완전히 막아줌)

- 유효하지 않은 포인터에 접근

- 이중 해제

- Memory Leak

단점 (주로 성능적 이슈)

- GC 알고리즘의 오버헤드

(프로그래머는 빤히 아는데… 왜 그걸 굳이 또 계산해가면서…)

- Timing 예측 불가 (중요한 타이밍에 버벅)

- 자원해제 시점을 모른다.

http://ko.wikipedia.org/wiki/쓰레기_수집_(컴퓨터_과학)

GC의 장점 + !단점이 가능할까 ?

Page 6: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준
Page 7: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준

Effective Modern C++ Study C++ Korea 7

• 직접적으로 Object를 소유하지 않음

• 여러 개의 std::shared_ptr이 하나의 Object를 공유

• Object는 마지막 std::shared_ptr이 사라지면 해제

#include <memory>

GC의 장점 : Object의 수명에 대해 신경 쓸 필요가 없다.

!단점 : 원하는 시점에 해제가 가능하다.

• 사용법은 생략

• 참조 사이트 : http://devluna.blogspot.kr/2014/12/stl-sharedptr-weakptr.html

Page 8: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준
Page 9: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준

Effective Modern C++ Study C++ Korea 9

해당 Object를 참조하고 있는 std::shared_ptr 의 개수

std::shared_ptr Constructor : Ref. Count ++

std::shared_ptr Destructor : Ref. Count - -

std::shared_ptr ::operator = : Left-hand Ref. Count ++, Right-hand Ref. Count - -

Atfer Ref. Count - - , if Ref. Count == 0 then delete object

Page 10: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준

Effective Modern C++ Study C++ Korea 10

1. Memory Issue

• Raw Pointer 크기의 2배 : Object Pointer + Control Block Pointer (include Ref. Count)

• Heap Memory (Dynamic Allocation) : Object 자체는 Ref. Count가 필요가 없다.

2. Performance Issue

• Atomic 연산 (sizse는 word)

• 대부분의 std::shared_ptr 은 Ref. Count ++

(Move 생성자, Move 연산자는 Ref. Count 변화 없음)

Page 11: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준
Page 12: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준

Effective Modern C++ Study C++ Korea 12

auto LogDel = [](T *pw)

{

makeLog(pw);

delete pw;

};

std::unique_ptr<T, decltype(LogDel)> UPW(new T, LogDel); // deleter type is part of ptr type

std::shared_ptr<T> SPW(new T, LogDel); // deleter type is not part of ptr type

- std::unique_ptr : template type의 부분

- std::shared_ptr : type의 일부가 아님

서로 다른 deleter를 가진 std::shared_ptr을 하나의 Container에 담을 수 있다.

Page 13: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준

Effective Modern C++ Study C++ Korea 13

- std::unique_ptr 은 custom deleter 크기를 포함

- std::shared_ptr 은 custom deleter 여부와 상관없이 무조건 Pointer 2개의 크기

• custom deleter는 function object 이다.

• 그럼 어디 저장 될까 ?

Control Block에 저장된다.

Page 14: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준
Page 15: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준

Effective Modern C++ Study C++ Korea 15

- Reference Count

- Weak Count

- Custom Deleter (if exists)

- Allocator (if exists)

Page 16: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준

Effective Modern C++ Study C++ Korea 16

- std::make_shared

- Unique-ownership Pointer (std::unique_ptr, std::auto_ptr)로 부터

std::shared_ptr 을 만들 때

- Raw Pointer로부터 std::shared_ptr 을 만들 때

OK

OK (std::shared_ptr 로 부터 std::unique_ptr 는 불가능 하니깐)

가만 ! 딱 봐도 먼가 이상한 Smell 이…. 스멜스멜….

Page 17: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준

Effective Modern C++ Study C++ Korea 17

auto P = new T;

{

std::shared_ptr<T> SP1(P, makeLog); // create control block for *p

{

std::shared_ptr<T> SP2(P, makeLog);// create 2nd control block for *p

}

} 여기서 SP2의 Ref. Count == 0 이 되니, P의 dtor가 호출.

여기서 SP1의 Ref. Count == 0 이 되니, P의 dtor가 호출.

가만…. 이미 P는 해제됬는데… 아놔 어떡하지 ???

1. Raw Pointer로 부터 std::shared_ptr을 생성하지 말자.

(하지만, custom deleter를 사용할려면 std::make_shared를 사용 못하는데 ???)

2. 어쩔수 없다면 Raw Pointer를 변수에 담지말고 new로 생성한 R-Value를 사용

std::shared_ptr<T> SP(new T, LogDel); // direct use of new

Page 18: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준
Page 19: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준

Effective Modern C++ Study C++ Korea 19

std::vector<std::shared_ptr<T>> T_History;

class T { public: void process(); };

void T::process() { T_History.emplace_back(this); // this is wrong

} this는 Raw Pointer

*this의 Control Block는 계속해서 만들어 질 것이다.

Page 20: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준

Effective Modern C++ Study C++ Korea 20

class T : public std::enable_shared_from_this<T>

{

public:

void process();

};

void T::process()

{

T_History.emplace_back( shared_from_this() );

}

근데… 너 좀 낮설다.

파생 클래스에서 파생 클래스의 템플릿 클래스를 상속받는다 ?

The Curiously Recurring Template Pattern (CRTP)

this로부터 std::shared_ptr은 만들지만 Control Block은 안만든다.

그런데…. 만약 그전에 만들어진 Control Block이 없다면 ?

아놔~ 예외를 발생시킨다.

어떻하지 ????

Factory Method Pattern

http://devluna.blogspot.kr/2015/01/factory-method-pattern.html

Page 21: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준

Effective Modern C++ Study C++ Korea 21

class T : public std::enable_shared_from_this<T>

{

public:

template<typename... Ts>

static std::shared_ptr<T> create(Ts&&... params);

private:

template<typename... Ts>

T(Ts&&... params);

};

생성자를 private에 선언

Factory method에서 std::shared<T>를 return

Page 22: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준
Page 23: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준

Effective Modern C++ Study C++ Korea 23

• Dynamic Allocation

• Size : few Words + custom deleter, allocator

• Virtual Function

• Atomic Calculation

Default는 3 Words

std::make_shared

Object Destructor

1,2 Instruction Cycle

이정도 Cost만 감당한다면, 수명관리를 해준다.

Page 24: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준
Page 25: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준

Effective Modern C++ Study C++ Korea 25

• std::shared_ptr는 단일 Pointer에 대해서만 동작

• 그럼 delete[ ] 를 이용해서 custom deleter를 만들면 ?

• std::shared_ptr에는 [ ] 연산자가 없다.

• 결정적으로 단일 개체에 대해서만 derived-to-base 포인트 변환을 지원

Page 26: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준
Page 27: [C++ korea] Effective Modern C++ study item 19 use shared ptr for shared ownership resource management +윤석준

Effective Modern C++ Study C++ Korea 27

• std::shared_ptr는 개체에 대한 수명관리를 Garbage Collection 만큼 편리하게 해준다.

• std::unique_ptr에 비해 std::shared_ptr는 개체가 2배 더 크고, Control Block에 대한 오버해

드가 발생하고, Reference Count에 대해서 Atomic 연산을 해야 한다.

• default 자원해제는 delete 지만 custom deleter도 지원한다. deleter의 타입은 std::shared_ptr

의 타입에 영향을 미치지 않는다.

• Raw Pointer를 변수로 만들어서 std::shared_ptr로 만들지 마라.