Resource Acquisition Is Initialization #
직역하면 자원의 획득은 초기화이다 ..자원(여기서 자원이란 메모리 뿐만 아니라 OS에 요청에서 얻어지는 모든건 ..)의
소멸(해제)은 Destructor(소멸자)에서 처리 하라는 말과 일맥 상통하는 말입니다.
소멸(해제)은 Destructor(소멸자)에서 처리 하라는 말과 일맥 상통하는 말입니다.
자원의 획득은 생성자에서, 그 자원의 소멸은 소멸자에서 처리하여 어떠한 경우에도
자원의 leak이 발생하지 않게 처리하자 란 생각입니다.
자원의 leak이 발생하지 않게 처리하자 란 생각입니다.
만약 다음과 같은 코드가 쓰레드의 함수안에서 실행 되고 있을때 ...
AFunction 함수에서 예외가 발생하여 Run함수를 빠져 나간다면 g_cs의 내용은
임계영역에서 못빠져 나온채 남아 있게 된니다.
그럼 나머지 쓰레드에서 실행되던 코드들은 EnterCriticalSection(&g_cs);
코드 앞에서 모두 대기하는 상태가 되어 프로그램이 DeadLock 상태에 빠지게 됩니다.
CRITICAL_SECTION g_cs; UINT Run(LPVOID) { if (조건) { EnterCriticalSection(&g_cs); // 임계영역에 들어갑니다. AFunction(); BFunction(); LeaveCriticalSection(&g_cs); // 임계영역에서 나옵니다. } else { // 다른 작업 } return 0; }
임계영역에서 못빠져 나온채 남아 있게 된니다.
그럼 나머지 쓰레드에서 실행되던 코드들은 EnterCriticalSection(&g_cs);
코드 앞에서 모두 대기하는 상태가 되어 프로그램이 DeadLock 상태에 빠지게 됩니다.
그러나 아래의 코드는 ...
class CriticalSection { public: CriticalSection(CRITICAL_SECTION *pcs) : pcs_(pcs) { EnterCriticalSection(pcs_); } ~CriticalSection() { LeaveCriticalSection(pcs_); }; private: CRITICAL_SECTION *pcs_; }; CRITICAL_SECTION g_cs; UINT Run(LPVOID) { if (조건) { // 임계영역에 들어갑니다. // 그리고 cs의 변수 생명이 끝날때 (if 문이 끝날때) // 소멸자가 호출되 임계영역의 자원을 해제 해줍니다. CriticalSection cs(&g_cs); AFunction(); bool b = BFunction(); if (!b) { return -1; } } else { 다른 작업 } return 0; }
AFunction혹은 BFunction에서 예외가 발생하던 중간의 return문을
만나서 쓰레드 함수를 탈출한다고 해도 CriticalSection의 소멸자에서
임계영역의 자원을 풀어주므로 보다 안전한 코드를 만들수가 있습니다.
만나서 쓰레드 함수를 탈출한다고 해도 CriticalSection의 소멸자에서
임계영역의 자원을 풀어주므로 보다 안전한 코드를 만들수가 있습니다.
이개념이 RAII(Resource Acquisition Is Initialization) 입니다.
이 RAII 철학을 바탕으로 만들어진 C++ 표준 객체가 std::auto_ptr 입니다.
std::auto_ptr은 생성자에서 할당된 포인터를 받아 소멸자에서
delete 시키는 기능을 가진 포인터타입의 래퍼 객체 입니다.
std::auto_ptr은 생성자에서 할당된 포인터를 받아 소멸자에서
delete 시키는 기능을 가진 포인터타입의 래퍼 객체 입니다.
std::auto_ptr은 다소 익숙하지 않은(일반포인터와 비교해)
소유정책을 가지고 있지만 호환성있는 표준 객체라는 점에서
눈여겨볼 아니 필요할때 꼭 사용되어져야 될 객체 입니다.
소유정책을 가지고 있지만 호환성있는 표준 객체라는 점에서
눈여겨볼 아니 필요할때 꼭 사용되어져야 될 객체 입니다.
#include <iostream> #include <memory> void f() { // string 객체를 동적으로 생성하고 명시적인 해제가 없지만 // std::auto_ptr의 소멸자에서 string 객체에 대한 할당된 포인터 객체를 // delete 해줄 것입니다. std::auto_ptr<string> p(new string("메롱")); std::cout << *p << std::endl; // 포인터와 같은 인터페이스를 가집니다. std::cout << p->lenght() << std::endl; } int main() { f(); }
이밖에 RAII의 기본철학을 이용한 COW(copy on write)기법이나
Reference Counting 기법을 이용한 smart포인터등 보다 안전하고
융통성있는 객체의 코드를 만들수 있을 것입니다.
Reference Counting 기법을 이용한 smart포인터등 보다 안전하고
융통성있는 객체의 코드를 만들수 있을 것입니다.
MS의 COM은 Reference Counting을 이용한 스마트 포인터로 핸들링 되며
_bstr_t 객체는 COW 타입을 사용해 성능 향상을 꾀한 예로 들수 있을 것입니다.
_bstr_t 객체는 COW 타입을 사용해 성능 향상을 꾀한 예로 들수 있을 것입니다.
이밖에도 boost(표준라이브러리는 아니지만 앞으로 표준화의 가능성이 높은 성능좋은
라이브러리)의 smart_ptr 객체들도 auto_ptr의 확장 개념으로서 제공되고 있습니다.
라이브러리)의 smart_ptr 객체들도 auto_ptr의 확장 개념으로서 제공되고 있습니다.
'Dev > C++' 카테고리의 다른 글
qsort vs sort (0) | 2008.05.01 |
---|---|
최소 완전한 클래스를 만들어라 (0) | 2008.05.01 |
상속되지 않는것 (0) | 2008.05.01 |
STL (0) | 2008.05.01 |
new 2 (0) | 2008.05.01 |