SlideShare a Scribd company logo
1 of 34
EFFECTIVE C++ 정리
Chapter 8
new / delete
new 처리자
ITEM 49
Item 49: new 처리자
• new 처리자
• 메모리 할당이 제대로 이루어지지 않은 경우 예외처리!
• 예외처리에 앞서 사용자의 커스텀 예외처리자, new-handler가 호출됨
• set_new_handler를 통해서 설정가능.
namespace std {
typedef void (*new_handler) ();
new_handler set_new_handler(new_handler p) throw ();
}
Item 49: new 처리자
• new 처리자에서 해줄 수 있는 일들
• 메모리 추가 확보
• 다른 new 처리자를 찾아서 호출
• NULL – 즉 default 예외처리
• 커스텀 예외처리 ( bad_alloc )
Item 49: new 처리자
• 클래스 별로 별도의 new handler를 사용하고 싶다면
• c++ 자체기능은 없으니 직접 만들어야함.
• 클래스 커스텀 set_new_handler
• new 처리자(함수)를 받아오는 역할
• operator new 오버라이딩
• 메모리 할당이 실패한 경우 클래스 자체 new-handler를 호출
Item 49: new 처리자
• set_new_handler
• new_handler Widget::set_new_handler(new_handler p) throw()
{
new_handler oldHandler = currentHandler;
currentHanlder = p;
return oldHandler;
}
Item 49: new 처리자
• operator new
• 표준 set_new_handler 함수에 Widget의 new_handler를 넘겨준다.
• new_handler 변경한 채로 new 호출, 종료 후 new_handler 복원
• 실패 시 bad_alloc 쓰로우 & new_handler 복원
• 위 작업에서 new_handler 복원 처리를 별도의 자원관리자를 통해서 만
들면 쉽게 구현가능
• new_handler 관리자 NewHandlerHolder를 만들자.
Item 49: new 처리자
• class NewHandlerHolder{
public:
explicit NewHandlerHolder(new_handler nh)
: handler (nh) { } //생성자에서 new_handler 받기
~NewHandlerHolder() //소멸자에서 set_new_handler호출
{ set_new_handler(handler); }
private:
new_handler handler;
}
Item 49: new 처리자
• Widget의 operator new
void* Widget::operator new(size_t size) throw(bad_alloc)
{
NewHandlerHolder h(set_new_handler(currentHolder));
// 기존의 newHandler를 저장한다.
return ::operator new(size); // 할당 작업 진행
//실패해도 NewHandlerHolder의 소멸자 호출  handler 복원
}
Item 49: new 처리자
• 템플릿화 해서 상속받아 사용할 수 있게 하자.
template<typename T>
class NewHandlerSupport {
public :
static new_handler set_new_handler( new_handler p );
static void* operator new(size_t size) throw(bad_alloc);
}
Item 49: new 처리자
• 상속 받아서 사용하는 방법
• class Widget : public NewHandlerSupport<Widget>
• template에서 T가 한번도 안쓰이는 데?
• 클래스별로 별도의 NewHandlerSupport가 필요함
• 클래스마다 각각 currentHandler가 다를 것이므로.
• T를 받아서 별도의 NewHandlerSupport를 만들어주기 위함
• CRTP라고 하는 자주 사용되는 패턴
Item 49: new 처리자
• 예외 불가 new ( 추가 이슈 )
• 예전에 할당실패 시 bad_alloc Throw말고 그냥 NULL을 리턴했다.
• 지금도 예외불가 new 하는 방법은 존재
new (std::nothrow) Widget ;
• 하지만 예외불가는 오직 Widget 공간 할당에 한해서만 적용된다.
• 내부 생성자에서 다시 new를 해서 실패한 예외는 적용 안됨
• 어쨌든 new_handler의 동작 구조를 잘 알아두자.
적절한 operator
new/delete
ITEM 50
Item 50: 적절한 operator new/delete
• 왜 new와 delete를 오버라이딩 하는가
• 잘못된 힙 사용 방지
• delete 두 번
• 할당 영역을 넘어선 접근 ( 오버런, 언더런 )
• 통계 수집
• 할당된 메모리 블록의 크기 / 사용기간 분포
• 메모리 사용패턴
Item 50: 적절한 operator new/delete
• 왜 new와 delete를 오버라이딩 하는가
• 할당 / 해제 성능 효율
• 특정한 조건에 할당/해제 작업에 최적화 할 수 있다.
• 고정크기의 객체만 만드는 경우
• 싱글 쓰레드 환경이 보장된 경우
• 공간 오버헤드를 최소화
• 안정적인 사용을 위해 다소 불필요한 메모리 공간(관리 영역) 발생
• 별도로 관리자가 따로 있다면 관리영역을 많이 줄일 수 있다.
Item 50: 적절한 operator new/delete
• 왜 new와 delete를 오버라이딩 하는가
• 바이트 정렬 보장
• 시스템 아키텍처를 최대한 활용하기 위해 메모리를 8바이트 단위 정렬할 수 있다.
• 기존 컴파일러가 이를 보장하지 않는 경우가 종종 있기 때문에 별도로 제작
• 같은 자료구조, 관계 있는 객체들의 물리적 locality 증대
• 객체를 별도로 할당을 관리하여 메모리의 locality를 증대시킬 수 있다.
• new / delete 시 별도의 동작 추가
Item 50: 적절한 operator new/delete
• 오버런 / 언더런 처리 operator new
void* operator new (size_t size) throw (bad_alloc)
{
size_t realSize = size + 2 * sizeof(int); //경계 표시영역 2개
void* pMem = malloc(realSize);
if(!pMem) throw bad_alloc();
*(static_cast<int*>(pMem)) = 0xDEADBEEF; //경계표시 1 (언더런 방지)
*(reinterpret_cast<int*>(static_cast<BYTE*> //경계표시 2 (오버런 방지)
(pMem) + realSize – sizeof(int))) = 0xDEADBEEF;
return static_cast<BYTE*>(pMem) + sizeof(int); //실제 메모리 시작위치 반환
}
Item 50: 적절한 operator new/delete
• 위 operator new의 문제점
• new_handler 호출 루프가 없음 (item 51에서 자세히)
• 바이트 정렬
• malloc해서 받은 값에서 int만큼 offset 이동시킨 주소를 리턴 하고 있음
• 메모리가 제대로 정렬된 상태가 아닐 가능성!
• 2^n 크기로 데이터들을 정렬해야 최적화된다.
• 아키텍처에 따라서 잘못된 동작을 야기할 수 도 있다.
• 멀티 쓰레드에 대한 개념 전혀 없음
Item 50: 적절한 operator new/delete
• 가능하면 전문가에게 맡기자
• 메모리 관리자를 잘 만들기란 쉽지 않은 일이다.
• 일반적인 경우 컴파일러의 기본 operator new/delete는 훌륭하다.
• 특별한 경우 라이브러리의 도움을 받자.
• boost::Pool : 크기가 작은 객체를 많이 할당/해제하는 경우
• 정렬 이슈/ 멀티 쓰레드 이슈가 잘 정리되어 있다.
• 직접 만들기 전에 라이브러리 코드를 보고 배우는 것도 도움이 될 것이다.
operator new/delete의
convention
ITEM 51
Item 51: operator new/delete의 convention
• operator new에서 convention
• 확실한 반환 값
• 요청된 메모리의 포인터를 반환
• 0 size 메모리 요청 대비
• 할당 실패시 우선 new 처리자 함수를 호출
• 그래도 안되면 bad_alloc throw
• 기존 new를 완전히 덮어 쓰지 말것 (item 52에서 자세히)
Item 51: operator new/delete의 convention
• 실제로 구현 하기
void* operator new (size_t size) throw (bad_alloc)
{
if( size == 0 ) size = 1; //0바이트 요청은 1바이트로 바꿔서
while( true ) { //할당이 되던가, bad_alloc이 뜨던가 둘중하나가 될때까지 반복
void* pMem = malloc( size );
if( pMem != NULL) return static_cast<T>(pMem);
//할당 실패시 현재 new_handler찾아서 실행
new_handler globalHandler = set_new_handler( NULL );
set_new_handler(globalHandler);
if( globalHandler ) (*globalHandler)( );
else throw bad_alloc( ); //new_handler 없으면 bad_alloc 처리
}
}
Item 51: operator new/delete의 convention
• 클래스 멤버변수 operator new의 convention
• operator new 또한 상속된다.
• 상속받은 클래스가 Base의 operator new를 호출했을 경우를 체크하자.
• item 50의 경우처럼 특수한 new를 만들었을 경우 기본 new를 호출할 수 있게
void* Base::operator new (size_t size) throw (bad_alloc) {
if( size != sizeof(Base) ) //틀린 크기가 들어오면 기존의 ::operator new사용
return ::operator new( size );
…
}
• 클래스의 크기는 최소 1이므로 0바이트 체크까지 되는 코드임
Item 51: operator new/delete의 convention
• operator new[] 에서 convention
• 단순히 주어진 사이즈의 메모리 덩어리를 할당하면 된다.
• 배열 정보를 함부로 추론하려 하지마라
• 몇 개의 객체가 들어올지 예측할 수 없다.
• new를 호출할 파생 클래스 객체의 사이즈를 알 수 없다.
• 안다고 해도 new [] 는 실제 객체 * 배열 길이 보다 더 큰 사이즈를 할당한다.
• item 16에서 언급한 헤더정보가 추가된다.
Item 51: operator new/delete의 convention
• operator delete에서 convention
• null포인터 exception만 조심하면 된다.
void operator delete( void* rawMemory ) throw ()
{
if ( rawMemory == NULL ) return; //NULL delete 방지
//메모리 해제 작업
…
}
Item 51: operator new/delete의 convention
• 클래스 멤버변수 operator delete 에서 convention
• 상속받은 클래스가 BASE의 operator delete를 호출하는 경우를 체크하자.
void Base::operator delete ( void* rawMemory, size_t size ) throw ()
{
if ( rawMemory == 0 ) return; //NULL 체크
if ( size != sizeof( Base ) ) {
::operator delete( rawMemory );
return;
}
//메모리 해제 작업
…
}
위치지정 new / delete
ITEM 52
Item 52: 위치지정 new / delete
• new 호출의 문제점
• Widget* pw = new Widget();
1. 메모리 할당을 위해 operater new 호출
2. Widget의 기본생성자 호출
• 메모리 할당은 잘 되었는데 Widget 생성자에서 exception?
• 런타임 시스템에서 operator new와 짝이 되는 operator delete를 호출해준다.
• 기본형의 경우는 문제없이 Pair로 잘 구성되어 있다.
• void operator new(size_t) throw (bad_alloc);
• void operator delete(void* rawMemory) throw( );
• 기본형이 아닌 operator new가 문제의 시작 (무엇이 Pair인가?)
Item 52: 위치지정 new / delete
• 기본형이 아닌 operator new (placement new)
• 할당시 log를 찍는 operator new 와 그 짝 delete
• void* operator new ( size_t size, ostream& logStream ) throw ( bad_alloc )
• void operator delete ( void* pMemory, size_t size) throw ( );
• 매개변수를 따로 받는 operator new 를 위치지정 new라고 한다.
• 자주 사용되던 미리 할당할 메모리 위치를 매개변수로 받는 new에서 시작
void operator new ( size_t size, void* pMemory) throw ( );
• ex : vector의 미사용 공간에 원소 객체를 할당-생성 할 때
Item 52: 위치지정 new / delete
• 런타임 시스템에서 Pair가 되는 operator delete를 찾는 법
• 추가 매개변수의 개수 및 타입이 똑같은 operator delete를 Pair로
• 위 로그 찍는 operator new/delete 예제에서는 서로 짝이 안 맞는다.
• 새로운 operator delete 선언
void operator delete( void* pMemory, ostream& logStream ) throw ();
• 이런 operator delete를 위치지정 delete라고 부른다.
Item 52: 위치지정 new / delete
• 만약 예외처리 없이 일반적으로 delete를 호출한다면?
• 런타임 시스템은 기본형의 operator delete를 호출한다.
• 위치지정 delete는 위치지정 new의 Pair가 필요할 때만 호출된다.
• 따라서 표준형태의 operator delete는 기본으로 항상 마련해야 한다.
• 추가적으로 위치지정 new를 썼다면 위치지정 delete도 만들어야 한다.
Item 52: 위치지정 new / delete
• operator new의 오버라이딩 문제 (이름 가림 이슈)
• 이름 문제의 디테일은 item 33 참조
• 전용의 operator new가 다른 operator new들을 가리지 않도록!
• Widget 클래스에서 위치지정 new만 선언/정의했다면?
Widget* pw = new Widget(); //error! 전역 operator new를 가린다.
• 전역에서 유효한 operator new 형태들
• void* operator new(std::size_t) throw (std::bad_alloc); //기본형 new
• void* operator new(std::size_t, void*) throw (); // 위치지정 new
• void* operator new(std::size_t, const std::nothrow_t&) throw(); //예외 불가 new
Item 52: 위치지정 new / delete
• 클래스에서 operator new를 정의하려면
• 모든 형태의 operator new및 pair가 되는 operator delete 정의필요
• 미리 operator들을 부를 수 있는 인터페이스 클래스를 만들어두자.
class StandardNewDeleteForms { //모든 종류의 operator new들을 선언한 인터페이스
public:
static void* operator new(std::size_t size) throw(std::bad_alloc)
{ return ::operator new(size); }
…
}
Item 52: 위치지정 new / delete
• 실제 사용 예
class Widget : public StandardNewDeleteForms { //인터페이스 상속
public:
using StandardNewDeleteForms::operator new; //이름영역 공유
using StandardNewDeleteForms::operator delete;
//별도의 위치지정 operator new /delete
static void* operator new(size_t size, void* pAlloc) throw (bad_alloc);
static void operator delete(void* pMemory, void* pAlloc) throw ();
}

More Related Content

What's hot

C++ Advanced 강의 2주차
C++ Advanced 강의 2주차C++ Advanced 강의 2주차
C++ Advanced 강의 2주차HyunJoon Park
 
Effective c++chapter1 and2
Effective c++chapter1 and2Effective c++chapter1 and2
Effective c++chapter1 and2성연 김
 
Effective c++chapter4
Effective c++chapter4Effective c++chapter4
Effective c++chapter4성연 김
 
Effective c++chapter3
Effective c++chapter3Effective c++chapter3
Effective c++chapter3성연 김
 
effective c++ chapter 3~4 정리
effective c++ chapter 3~4 정리effective c++ chapter 3~4 정리
effective c++ chapter 3~4 정리Injae Lee
 
이펙티브 C++ 공부
이펙티브 C++ 공부이펙티브 C++ 공부
이펙티브 C++ 공부quxn6
 
C++ Advanced 강의 4주차
 C++ Advanced 강의 4주차 C++ Advanced 강의 4주차
C++ Advanced 강의 4주차HyunJoon Park
 
이펙티브 C++ 5,6 장 스터디
이펙티브 C++ 5,6 장 스터디이펙티브 C++ 5,6 장 스터디
이펙티브 C++ 5,6 장 스터디quxn6
 
이펙티브 C++ 스터디
이펙티브 C++ 스터디이펙티브 C++ 스터디
이펙티브 C++ 스터디quxn6
 
More effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshinMore effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshinDong Chan Shin
 
C++ Advanced 강의 1주차
C++ Advanced 강의 1주차C++ Advanced 강의 1주차
C++ Advanced 강의 1주차HyunJoon Park
 
이펙티브 C++ (7~9)
이펙티브 C++ (7~9)이펙티브 C++ (7~9)
이펙티브 C++ (7~9)익성 조
 
프론트엔드스터디 E04 js function
프론트엔드스터디 E04 js function프론트엔드스터디 E04 js function
프론트엔드스터디 E04 js functionYoung-Beom Rhee
 
More effective c++ 2
More effective c++ 2More effective c++ 2
More effective c++ 2현찬 양
 
프론트엔드스터디 E03 - Javascript intro.
프론트엔드스터디 E03 - Javascript intro.프론트엔드스터디 E03 - Javascript intro.
프론트엔드스터디 E03 - Javascript intro.Young-Beom Rhee
 
More effective c++ 항목30부터
More effective c++ 항목30부터More effective c++ 항목30부터
More effective c++ 항목30부터Dong Chan Shin
 
[D2 COMMUNITY] ECMAScript 2015 S67 seminar - 1. primitive
[D2 COMMUNITY] ECMAScript 2015 S67 seminar - 1. primitive[D2 COMMUNITY] ECMAScript 2015 S67 seminar - 1. primitive
[D2 COMMUNITY] ECMAScript 2015 S67 seminar - 1. primitiveNAVER D2
 
프론트엔드스터디 E05 js closure oop
프론트엔드스터디 E05 js closure oop프론트엔드스터디 E05 js closure oop
프론트엔드스터디 E05 js closure oopYoung-Beom Rhee
 
Effective c++ 4
Effective c++ 4Effective c++ 4
Effective c++ 4현찬 양
 

What's hot (20)

C++ Advanced 강의 2주차
C++ Advanced 강의 2주차C++ Advanced 강의 2주차
C++ Advanced 강의 2주차
 
Effective c++chapter1 and2
Effective c++chapter1 and2Effective c++chapter1 and2
Effective c++chapter1 and2
 
Effective c++chapter4
Effective c++chapter4Effective c++chapter4
Effective c++chapter4
 
Effective c++chapter3
Effective c++chapter3Effective c++chapter3
Effective c++chapter3
 
effective c++ chapter 3~4 정리
effective c++ chapter 3~4 정리effective c++ chapter 3~4 정리
effective c++ chapter 3~4 정리
 
이펙티브 C++ 공부
이펙티브 C++ 공부이펙티브 C++ 공부
이펙티브 C++ 공부
 
C++ Advanced 강의 4주차
 C++ Advanced 강의 4주차 C++ Advanced 강의 4주차
C++ Advanced 강의 4주차
 
이펙티브 C++ 5,6 장 스터디
이펙티브 C++ 5,6 장 스터디이펙티브 C++ 5,6 장 스터디
이펙티브 C++ 5,6 장 스터디
 
이펙티브 C++ 스터디
이펙티브 C++ 스터디이펙티브 C++ 스터디
이펙티브 C++ 스터디
 
More effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshinMore effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshin
 
Exception&log
Exception&logException&log
Exception&log
 
C++ Advanced 강의 1주차
C++ Advanced 강의 1주차C++ Advanced 강의 1주차
C++ Advanced 강의 1주차
 
이펙티브 C++ (7~9)
이펙티브 C++ (7~9)이펙티브 C++ (7~9)
이펙티브 C++ (7~9)
 
프론트엔드스터디 E04 js function
프론트엔드스터디 E04 js function프론트엔드스터디 E04 js function
프론트엔드스터디 E04 js function
 
More effective c++ 2
More effective c++ 2More effective c++ 2
More effective c++ 2
 
프론트엔드스터디 E03 - Javascript intro.
프론트엔드스터디 E03 - Javascript intro.프론트엔드스터디 E03 - Javascript intro.
프론트엔드스터디 E03 - Javascript intro.
 
More effective c++ 항목30부터
More effective c++ 항목30부터More effective c++ 항목30부터
More effective c++ 항목30부터
 
[D2 COMMUNITY] ECMAScript 2015 S67 seminar - 1. primitive
[D2 COMMUNITY] ECMAScript 2015 S67 seminar - 1. primitive[D2 COMMUNITY] ECMAScript 2015 S67 seminar - 1. primitive
[D2 COMMUNITY] ECMAScript 2015 S67 seminar - 1. primitive
 
프론트엔드스터디 E05 js closure oop
프론트엔드스터디 E05 js closure oop프론트엔드스터디 E05 js closure oop
프론트엔드스터디 E05 js closure oop
 
Effective c++ 4
Effective c++ 4Effective c++ 4
Effective c++ 4
 

Viewers also liked

[C++ korea] effective modern c++ study item 2 understanding auto type deduc...
[C++ korea] effective modern c++ study   item 2 understanding auto type deduc...[C++ korea] effective modern c++ study   item 2 understanding auto type deduc...
[C++ korea] effective modern c++ study item 2 understanding auto type deduc...Seok-joon Yun
 
Pro typescript.ch07.Exception, Memory, Performance
Pro typescript.ch07.Exception, Memory, PerformancePro typescript.ch07.Exception, Memory, Performance
Pro typescript.ch07.Exception, Memory, PerformanceSeok-joon Yun
 
[C++ korea] Effective Modern C++ study item 19 use shared ptr for shared owne...
[C++ korea] Effective Modern C++ study item 19 use shared ptr for shared owne...[C++ korea] Effective Modern C++ study item 19 use shared ptr for shared owne...
[C++ korea] Effective Modern C++ study item 19 use shared ptr for shared owne...Seok-joon Yun
 
Visual studio 사용 설명서(고급)
Visual studio 사용 설명서(고급)Visual studio 사용 설명서(고급)
Visual studio 사용 설명서(고급)Lusain Kim
 
Effective c++ 1
Effective c++ 1Effective c++ 1
Effective c++ 1현찬 양
 
[KGC 2012]Boost.asio를 이용한 네트웍 프로그래밍
[KGC 2012]Boost.asio를 이용한 네트웍 프로그래밍[KGC 2012]Boost.asio를 이용한 네트웍 프로그래밍
[KGC 2012]Boost.asio를 이용한 네트웍 프로그래밍흥배 최
 
Next 게임 실전 프로젝트 슬라이드
Next 게임 실전 프로젝트 슬라이드Next 게임 실전 프로젝트 슬라이드
Next 게임 실전 프로젝트 슬라이드Nam Hyeonuk
 
Iocp 기본 구조 이해
Iocp 기본 구조 이해Iocp 기본 구조 이해
Iocp 기본 구조 이해Nam Hyeonuk
 
게임서버프로그래밍 #1 - IOCP
게임서버프로그래밍 #1 - IOCP게임서버프로그래밍 #1 - IOCP
게임서버프로그래밍 #1 - IOCPSeungmo Koo
 
게임서버프로그래밍 #5 - 데이터베이스 핸들링
게임서버프로그래밍 #5 - 데이터베이스 핸들링게임서버프로그래밍 #5 - 데이터베이스 핸들링
게임서버프로그래밍 #5 - 데이터베이스 핸들링Seungmo Koo
 
게임서버프로그래밍 #6 - 예외처리 및 로깅
게임서버프로그래밍 #6 - 예외처리 및 로깅게임서버프로그래밍 #6 - 예외처리 및 로깅
게임서버프로그래밍 #6 - 예외처리 및 로깅Seungmo Koo
 
게임서버프로그래밍 #2 - IOCP Adv
게임서버프로그래밍 #2 - IOCP Adv게임서버프로그래밍 #2 - IOCP Adv
게임서버프로그래밍 #2 - IOCP AdvSeungmo Koo
 
게임서버프로그래밍 #3 - 메모리 및 오브젝트 풀링
게임서버프로그래밍 #3 - 메모리 및 오브젝트 풀링게임서버프로그래밍 #3 - 메모리 및 오브젝트 풀링
게임서버프로그래밍 #3 - 메모리 및 오브젝트 풀링Seungmo Koo
 
게임서버프로그래밍 #4 - 멀티스레드 프로그래밍
게임서버프로그래밍 #4 - 멀티스레드 프로그래밍게임서버프로그래밍 #4 - 멀티스레드 프로그래밍
게임서버프로그래밍 #4 - 멀티스레드 프로그래밍Seungmo Koo
 
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델Seungmo Koo
 
게임서버프로그래밍 #7 - 패킷핸들링 및 암호화
게임서버프로그래밍 #7 - 패킷핸들링 및 암호화게임서버프로그래밍 #7 - 패킷핸들링 및 암호화
게임서버프로그래밍 #7 - 패킷핸들링 및 암호화Seungmo Koo
 
시즌 2: 멀티쓰레드 프로그래밍이 왜이리 힘드나요?
시즌 2: 멀티쓰레드 프로그래밍이 왜이리 힘드나요?시즌 2: 멀티쓰레드 프로그래밍이 왜이리 힘드나요?
시즌 2: 멀티쓰레드 프로그래밍이 왜이리 힘드나요?내훈 정
 
게임서버프로그래밍 #8 - 성능 평가
게임서버프로그래밍 #8 - 성능 평가게임서버프로그래밍 #8 - 성능 평가
게임서버프로그래밍 #8 - 성능 평가Seungmo Koo
 

Viewers also liked (20)

[C++ korea] effective modern c++ study item 2 understanding auto type deduc...
[C++ korea] effective modern c++ study   item 2 understanding auto type deduc...[C++ korea] effective modern c++ study   item 2 understanding auto type deduc...
[C++ korea] effective modern c++ study item 2 understanding auto type deduc...
 
Pro typescript.ch07.Exception, Memory, Performance
Pro typescript.ch07.Exception, Memory, PerformancePro typescript.ch07.Exception, Memory, Performance
Pro typescript.ch07.Exception, Memory, Performance
 
[C++ korea] Effective Modern C++ study item 19 use shared ptr for shared owne...
[C++ korea] Effective Modern C++ study item 19 use shared ptr for shared owne...[C++ korea] Effective Modern C++ study item 19 use shared ptr for shared owne...
[C++ korea] Effective Modern C++ study item 19 use shared ptr for shared owne...
 
Visual studio 사용 설명서(고급)
Visual studio 사용 설명서(고급)Visual studio 사용 설명서(고급)
Visual studio 사용 설명서(고급)
 
Effective c++ 1
Effective c++ 1Effective c++ 1
Effective c++ 1
 
Ndc12 2
Ndc12 2Ndc12 2
Ndc12 2
 
Gpg study5.5
Gpg study5.5Gpg study5.5
Gpg study5.5
 
[KGC 2012]Boost.asio를 이용한 네트웍 프로그래밍
[KGC 2012]Boost.asio를 이용한 네트웍 프로그래밍[KGC 2012]Boost.asio를 이용한 네트웍 프로그래밍
[KGC 2012]Boost.asio를 이용한 네트웍 프로그래밍
 
Next 게임 실전 프로젝트 슬라이드
Next 게임 실전 프로젝트 슬라이드Next 게임 실전 프로젝트 슬라이드
Next 게임 실전 프로젝트 슬라이드
 
Iocp 기본 구조 이해
Iocp 기본 구조 이해Iocp 기본 구조 이해
Iocp 기본 구조 이해
 
게임서버프로그래밍 #1 - IOCP
게임서버프로그래밍 #1 - IOCP게임서버프로그래밍 #1 - IOCP
게임서버프로그래밍 #1 - IOCP
 
게임서버프로그래밍 #5 - 데이터베이스 핸들링
게임서버프로그래밍 #5 - 데이터베이스 핸들링게임서버프로그래밍 #5 - 데이터베이스 핸들링
게임서버프로그래밍 #5 - 데이터베이스 핸들링
 
게임서버프로그래밍 #6 - 예외처리 및 로깅
게임서버프로그래밍 #6 - 예외처리 및 로깅게임서버프로그래밍 #6 - 예외처리 및 로깅
게임서버프로그래밍 #6 - 예외처리 및 로깅
 
게임서버프로그래밍 #2 - IOCP Adv
게임서버프로그래밍 #2 - IOCP Adv게임서버프로그래밍 #2 - IOCP Adv
게임서버프로그래밍 #2 - IOCP Adv
 
게임서버프로그래밍 #3 - 메모리 및 오브젝트 풀링
게임서버프로그래밍 #3 - 메모리 및 오브젝트 풀링게임서버프로그래밍 #3 - 메모리 및 오브젝트 풀링
게임서버프로그래밍 #3 - 메모리 및 오브젝트 풀링
 
게임서버프로그래밍 #4 - 멀티스레드 프로그래밍
게임서버프로그래밍 #4 - 멀티스레드 프로그래밍게임서버프로그래밍 #4 - 멀티스레드 프로그래밍
게임서버프로그래밍 #4 - 멀티스레드 프로그래밍
 
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
 
게임서버프로그래밍 #7 - 패킷핸들링 및 암호화
게임서버프로그래밍 #7 - 패킷핸들링 및 암호화게임서버프로그래밍 #7 - 패킷핸들링 및 암호화
게임서버프로그래밍 #7 - 패킷핸들링 및 암호화
 
시즌 2: 멀티쓰레드 프로그래밍이 왜이리 힘드나요?
시즌 2: 멀티쓰레드 프로그래밍이 왜이리 힘드나요?시즌 2: 멀티쓰레드 프로그래밍이 왜이리 힘드나요?
시즌 2: 멀티쓰레드 프로그래밍이 왜이리 힘드나요?
 
게임서버프로그래밍 #8 - 성능 평가
게임서버프로그래밍 #8 - 성능 평가게임서버프로그래밍 #8 - 성능 평가
게임서버프로그래밍 #8 - 성능 평가
 

Similar to Effective c++ 정리 chapter 8

Effective c++ item49
Effective c++ item49Effective c++ item49
Effective c++ item49진화 손
 
More effective c++ chapter1,2
More effective c++ chapter1,2More effective c++ chapter1,2
More effective c++ chapter1,2문익 장
 
Effective c++ chapter 7,8
Effective c++ chapter 7,8Effective c++ chapter 7,8
Effective c++ chapter 7,8문익 장
 
Effective modern cpp item18, 19
Effective modern cpp item18, 19Effective modern cpp item18, 19
Effective modern cpp item18, 19진화 손
 
Api design for c++ pattern
Api design for c++ patternApi design for c++ pattern
Api design for c++ patternjinho park
 
Api design for c++ ch3 pattern
Api design for c++ ch3 patternApi design for c++ ch3 pattern
Api design for c++ ch3 patternjinho park
 
Effective c++ 1~8장
Effective c++ 1~8장 Effective c++ 1~8장
Effective c++ 1~8장 Shin heemin
 

Similar to Effective c++ 정리 chapter 8 (8)

Effective c++ item49
Effective c++ item49Effective c++ item49
Effective c++ item49
 
More effective c++ chapter1,2
More effective c++ chapter1,2More effective c++ chapter1,2
More effective c++ chapter1,2
 
Effective c++ chapter 7,8
Effective c++ chapter 7,8Effective c++ chapter 7,8
Effective c++ chapter 7,8
 
Effective modern cpp item18, 19
Effective modern cpp item18, 19Effective modern cpp item18, 19
Effective modern cpp item18, 19
 
EC 789
EC 789EC 789
EC 789
 
Api design for c++ pattern
Api design for c++ patternApi design for c++ pattern
Api design for c++ pattern
 
Api design for c++ ch3 pattern
Api design for c++ ch3 patternApi design for c++ ch3 pattern
Api design for c++ ch3 pattern
 
Effective c++ 1~8장
Effective c++ 1~8장 Effective c++ 1~8장
Effective c++ 1~8장
 

Effective c++ 정리 chapter 8

  • 3. Item 49: new 처리자 • new 처리자 • 메모리 할당이 제대로 이루어지지 않은 경우 예외처리! • 예외처리에 앞서 사용자의 커스텀 예외처리자, new-handler가 호출됨 • set_new_handler를 통해서 설정가능. namespace std { typedef void (*new_handler) (); new_handler set_new_handler(new_handler p) throw (); }
  • 4. Item 49: new 처리자 • new 처리자에서 해줄 수 있는 일들 • 메모리 추가 확보 • 다른 new 처리자를 찾아서 호출 • NULL – 즉 default 예외처리 • 커스텀 예외처리 ( bad_alloc )
  • 5. Item 49: new 처리자 • 클래스 별로 별도의 new handler를 사용하고 싶다면 • c++ 자체기능은 없으니 직접 만들어야함. • 클래스 커스텀 set_new_handler • new 처리자(함수)를 받아오는 역할 • operator new 오버라이딩 • 메모리 할당이 실패한 경우 클래스 자체 new-handler를 호출
  • 6. Item 49: new 처리자 • set_new_handler • new_handler Widget::set_new_handler(new_handler p) throw() { new_handler oldHandler = currentHandler; currentHanlder = p; return oldHandler; }
  • 7. Item 49: new 처리자 • operator new • 표준 set_new_handler 함수에 Widget의 new_handler를 넘겨준다. • new_handler 변경한 채로 new 호출, 종료 후 new_handler 복원 • 실패 시 bad_alloc 쓰로우 & new_handler 복원 • 위 작업에서 new_handler 복원 처리를 별도의 자원관리자를 통해서 만 들면 쉽게 구현가능 • new_handler 관리자 NewHandlerHolder를 만들자.
  • 8. Item 49: new 처리자 • class NewHandlerHolder{ public: explicit NewHandlerHolder(new_handler nh) : handler (nh) { } //생성자에서 new_handler 받기 ~NewHandlerHolder() //소멸자에서 set_new_handler호출 { set_new_handler(handler); } private: new_handler handler; }
  • 9. Item 49: new 처리자 • Widget의 operator new void* Widget::operator new(size_t size) throw(bad_alloc) { NewHandlerHolder h(set_new_handler(currentHolder)); // 기존의 newHandler를 저장한다. return ::operator new(size); // 할당 작업 진행 //실패해도 NewHandlerHolder의 소멸자 호출  handler 복원 }
  • 10. Item 49: new 처리자 • 템플릿화 해서 상속받아 사용할 수 있게 하자. template<typename T> class NewHandlerSupport { public : static new_handler set_new_handler( new_handler p ); static void* operator new(size_t size) throw(bad_alloc); }
  • 11. Item 49: new 처리자 • 상속 받아서 사용하는 방법 • class Widget : public NewHandlerSupport<Widget> • template에서 T가 한번도 안쓰이는 데? • 클래스별로 별도의 NewHandlerSupport가 필요함 • 클래스마다 각각 currentHandler가 다를 것이므로. • T를 받아서 별도의 NewHandlerSupport를 만들어주기 위함 • CRTP라고 하는 자주 사용되는 패턴
  • 12. Item 49: new 처리자 • 예외 불가 new ( 추가 이슈 ) • 예전에 할당실패 시 bad_alloc Throw말고 그냥 NULL을 리턴했다. • 지금도 예외불가 new 하는 방법은 존재 new (std::nothrow) Widget ; • 하지만 예외불가는 오직 Widget 공간 할당에 한해서만 적용된다. • 내부 생성자에서 다시 new를 해서 실패한 예외는 적용 안됨 • 어쨌든 new_handler의 동작 구조를 잘 알아두자.
  • 14. Item 50: 적절한 operator new/delete • 왜 new와 delete를 오버라이딩 하는가 • 잘못된 힙 사용 방지 • delete 두 번 • 할당 영역을 넘어선 접근 ( 오버런, 언더런 ) • 통계 수집 • 할당된 메모리 블록의 크기 / 사용기간 분포 • 메모리 사용패턴
  • 15. Item 50: 적절한 operator new/delete • 왜 new와 delete를 오버라이딩 하는가 • 할당 / 해제 성능 효율 • 특정한 조건에 할당/해제 작업에 최적화 할 수 있다. • 고정크기의 객체만 만드는 경우 • 싱글 쓰레드 환경이 보장된 경우 • 공간 오버헤드를 최소화 • 안정적인 사용을 위해 다소 불필요한 메모리 공간(관리 영역) 발생 • 별도로 관리자가 따로 있다면 관리영역을 많이 줄일 수 있다.
  • 16. Item 50: 적절한 operator new/delete • 왜 new와 delete를 오버라이딩 하는가 • 바이트 정렬 보장 • 시스템 아키텍처를 최대한 활용하기 위해 메모리를 8바이트 단위 정렬할 수 있다. • 기존 컴파일러가 이를 보장하지 않는 경우가 종종 있기 때문에 별도로 제작 • 같은 자료구조, 관계 있는 객체들의 물리적 locality 증대 • 객체를 별도로 할당을 관리하여 메모리의 locality를 증대시킬 수 있다. • new / delete 시 별도의 동작 추가
  • 17. Item 50: 적절한 operator new/delete • 오버런 / 언더런 처리 operator new void* operator new (size_t size) throw (bad_alloc) { size_t realSize = size + 2 * sizeof(int); //경계 표시영역 2개 void* pMem = malloc(realSize); if(!pMem) throw bad_alloc(); *(static_cast<int*>(pMem)) = 0xDEADBEEF; //경계표시 1 (언더런 방지) *(reinterpret_cast<int*>(static_cast<BYTE*> //경계표시 2 (오버런 방지) (pMem) + realSize – sizeof(int))) = 0xDEADBEEF; return static_cast<BYTE*>(pMem) + sizeof(int); //실제 메모리 시작위치 반환 }
  • 18. Item 50: 적절한 operator new/delete • 위 operator new의 문제점 • new_handler 호출 루프가 없음 (item 51에서 자세히) • 바이트 정렬 • malloc해서 받은 값에서 int만큼 offset 이동시킨 주소를 리턴 하고 있음 • 메모리가 제대로 정렬된 상태가 아닐 가능성! • 2^n 크기로 데이터들을 정렬해야 최적화된다. • 아키텍처에 따라서 잘못된 동작을 야기할 수 도 있다. • 멀티 쓰레드에 대한 개념 전혀 없음
  • 19. Item 50: 적절한 operator new/delete • 가능하면 전문가에게 맡기자 • 메모리 관리자를 잘 만들기란 쉽지 않은 일이다. • 일반적인 경우 컴파일러의 기본 operator new/delete는 훌륭하다. • 특별한 경우 라이브러리의 도움을 받자. • boost::Pool : 크기가 작은 객체를 많이 할당/해제하는 경우 • 정렬 이슈/ 멀티 쓰레드 이슈가 잘 정리되어 있다. • 직접 만들기 전에 라이브러리 코드를 보고 배우는 것도 도움이 될 것이다.
  • 21. Item 51: operator new/delete의 convention • operator new에서 convention • 확실한 반환 값 • 요청된 메모리의 포인터를 반환 • 0 size 메모리 요청 대비 • 할당 실패시 우선 new 처리자 함수를 호출 • 그래도 안되면 bad_alloc throw • 기존 new를 완전히 덮어 쓰지 말것 (item 52에서 자세히)
  • 22. Item 51: operator new/delete의 convention • 실제로 구현 하기 void* operator new (size_t size) throw (bad_alloc) { if( size == 0 ) size = 1; //0바이트 요청은 1바이트로 바꿔서 while( true ) { //할당이 되던가, bad_alloc이 뜨던가 둘중하나가 될때까지 반복 void* pMem = malloc( size ); if( pMem != NULL) return static_cast<T>(pMem); //할당 실패시 현재 new_handler찾아서 실행 new_handler globalHandler = set_new_handler( NULL ); set_new_handler(globalHandler); if( globalHandler ) (*globalHandler)( ); else throw bad_alloc( ); //new_handler 없으면 bad_alloc 처리 } }
  • 23. Item 51: operator new/delete의 convention • 클래스 멤버변수 operator new의 convention • operator new 또한 상속된다. • 상속받은 클래스가 Base의 operator new를 호출했을 경우를 체크하자. • item 50의 경우처럼 특수한 new를 만들었을 경우 기본 new를 호출할 수 있게 void* Base::operator new (size_t size) throw (bad_alloc) { if( size != sizeof(Base) ) //틀린 크기가 들어오면 기존의 ::operator new사용 return ::operator new( size ); … } • 클래스의 크기는 최소 1이므로 0바이트 체크까지 되는 코드임
  • 24. Item 51: operator new/delete의 convention • operator new[] 에서 convention • 단순히 주어진 사이즈의 메모리 덩어리를 할당하면 된다. • 배열 정보를 함부로 추론하려 하지마라 • 몇 개의 객체가 들어올지 예측할 수 없다. • new를 호출할 파생 클래스 객체의 사이즈를 알 수 없다. • 안다고 해도 new [] 는 실제 객체 * 배열 길이 보다 더 큰 사이즈를 할당한다. • item 16에서 언급한 헤더정보가 추가된다.
  • 25. Item 51: operator new/delete의 convention • operator delete에서 convention • null포인터 exception만 조심하면 된다. void operator delete( void* rawMemory ) throw () { if ( rawMemory == NULL ) return; //NULL delete 방지 //메모리 해제 작업 … }
  • 26. Item 51: operator new/delete의 convention • 클래스 멤버변수 operator delete 에서 convention • 상속받은 클래스가 BASE의 operator delete를 호출하는 경우를 체크하자. void Base::operator delete ( void* rawMemory, size_t size ) throw () { if ( rawMemory == 0 ) return; //NULL 체크 if ( size != sizeof( Base ) ) { ::operator delete( rawMemory ); return; } //메모리 해제 작업 … }
  • 27. 위치지정 new / delete ITEM 52
  • 28. Item 52: 위치지정 new / delete • new 호출의 문제점 • Widget* pw = new Widget(); 1. 메모리 할당을 위해 operater new 호출 2. Widget의 기본생성자 호출 • 메모리 할당은 잘 되었는데 Widget 생성자에서 exception? • 런타임 시스템에서 operator new와 짝이 되는 operator delete를 호출해준다. • 기본형의 경우는 문제없이 Pair로 잘 구성되어 있다. • void operator new(size_t) throw (bad_alloc); • void operator delete(void* rawMemory) throw( ); • 기본형이 아닌 operator new가 문제의 시작 (무엇이 Pair인가?)
  • 29. Item 52: 위치지정 new / delete • 기본형이 아닌 operator new (placement new) • 할당시 log를 찍는 operator new 와 그 짝 delete • void* operator new ( size_t size, ostream& logStream ) throw ( bad_alloc ) • void operator delete ( void* pMemory, size_t size) throw ( ); • 매개변수를 따로 받는 operator new 를 위치지정 new라고 한다. • 자주 사용되던 미리 할당할 메모리 위치를 매개변수로 받는 new에서 시작 void operator new ( size_t size, void* pMemory) throw ( ); • ex : vector의 미사용 공간에 원소 객체를 할당-생성 할 때
  • 30. Item 52: 위치지정 new / delete • 런타임 시스템에서 Pair가 되는 operator delete를 찾는 법 • 추가 매개변수의 개수 및 타입이 똑같은 operator delete를 Pair로 • 위 로그 찍는 operator new/delete 예제에서는 서로 짝이 안 맞는다. • 새로운 operator delete 선언 void operator delete( void* pMemory, ostream& logStream ) throw (); • 이런 operator delete를 위치지정 delete라고 부른다.
  • 31. Item 52: 위치지정 new / delete • 만약 예외처리 없이 일반적으로 delete를 호출한다면? • 런타임 시스템은 기본형의 operator delete를 호출한다. • 위치지정 delete는 위치지정 new의 Pair가 필요할 때만 호출된다. • 따라서 표준형태의 operator delete는 기본으로 항상 마련해야 한다. • 추가적으로 위치지정 new를 썼다면 위치지정 delete도 만들어야 한다.
  • 32. Item 52: 위치지정 new / delete • operator new의 오버라이딩 문제 (이름 가림 이슈) • 이름 문제의 디테일은 item 33 참조 • 전용의 operator new가 다른 operator new들을 가리지 않도록! • Widget 클래스에서 위치지정 new만 선언/정의했다면? Widget* pw = new Widget(); //error! 전역 operator new를 가린다. • 전역에서 유효한 operator new 형태들 • void* operator new(std::size_t) throw (std::bad_alloc); //기본형 new • void* operator new(std::size_t, void*) throw (); // 위치지정 new • void* operator new(std::size_t, const std::nothrow_t&) throw(); //예외 불가 new
  • 33. Item 52: 위치지정 new / delete • 클래스에서 operator new를 정의하려면 • 모든 형태의 operator new및 pair가 되는 operator delete 정의필요 • 미리 operator들을 부를 수 있는 인터페이스 클래스를 만들어두자. class StandardNewDeleteForms { //모든 종류의 operator new들을 선언한 인터페이스 public: static void* operator new(std::size_t size) throw(std::bad_alloc) { return ::operator new(size); } … }
  • 34. Item 52: 위치지정 new / delete • 실제 사용 예 class Widget : public StandardNewDeleteForms { //인터페이스 상속 public: using StandardNewDeleteForms::operator new; //이름영역 공유 using StandardNewDeleteForms::operator delete; //별도의 위치지정 operator new /delete static void* operator new(size_t size, void* pAlloc) throw (bad_alloc); static void operator delete(void* pMemory, void* pAlloc) throw (); }