일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 |
[GGG] 신입 개발자를 위한 메모리 사용법 2. 신영진 pop@jiniya.net http://www.jiniya.net 6월호 기사에서 우리는 함수로 넘어오는 인자와 함수의 리턴 값에 사용되는 메모리의 종류와 사용 방법에 대해서 배웠다. 하지만 실제 프로그램을 작성할 때에는 인자와 리턴 값 외에도 신경 쓸 부분이 많다. 이번 시간에는 Windows 메시지에 사용된 복잡한 특성의 메모리와 스마트 포인터를 사용해서 메모리 릭을 방지하는 방법에 대해서 살펴본다. 복잡한 특성을 가진 메모리 LVN_GETDISPINFO는 리스트 뷰 컨트롤에서 추가한 아이템의 내용을 콜백으로 설정하도록 했을 때 날라오는 메시지다. 이 메시지의 파라미터로는 LVITEM이 넘어온다. 대부분의 초급 Visual C++ 책에서는 이 메시지 핸들러에 다음과 같은 코드를 포함하고 있다. [CPP]strcpy(item->pszText, _T(“태권브이”));[/CPP]아주 단순한 코드다. 그런 만큼 책에는 저 코드에 대한 어떠한 설명도 없다. 하지만 우리는 저러한 코드를 보면 “pszText에 대한 할당과 해제를 책임지는 것은 누구일까?”라는 질문을 꼭 던져야 한다. pszText는 꽤나 복잡한 성격의 포인터다. 복사할 문자열의 길이가 cchTextMax보다 작다면 위와 같이 문자열 복사를 하면 된다. 만약 복사할 문자열이 더 길다면 pszText가 가리키는 포인터를 아래와 같이 바꾸어 주면 된다. 이 때 한 가지 주의해야 할 점은 pszText가 가리키고 있는 메모리가 적어도 두 번의 LVN_GETDISPINFO 메시지를 더 받은 다음 파괴되어야 한다는 점이다. [CPP]item->pszText = _T(“태권 브이”);[/CPP]위와 같이 복잡한 특성은 LVN_GETDISPINFO를 설계한 사람이 아니라면 알 수 없기 때문에 API를 만든 사람은 친절하게 매뉴얼에(MSDN) 설명을 적어 놓았다. 따라서 위와 같이 이상하게 보이는 메모리가 있다면 반드시 매뉴얼을 통해서 그 메모리를 다루는 방법에 대해서 숙지한 다음 사용하도록 해야 한다. 스마트 포인터 스마트 포인터는 RAII (Resource acquisition is initialization)의 개념을 가장 잘 활용한 예 중의 하나다. RAII란 생성자에서 자원을 획득하고, 소멸자에서 자원을 자동적으로 파괴해야 한다는 원칙이다. <리스트 1>을 살펴보자. 할당한 메모리 ptr이, some_condition인 경우는 해제되지 않고 리턴 하기 때문에 릭이 생긴다. 바보 같은 코드처럼 보이지만 할당된 자원이 많고, 함수가 복잡해질수록 이러한 일은 더욱 쉽게 일어난다. 이러한 문제점을 스마트 포인터를 사용해서 변경한 코드가 <리스트 2>다. <리스트 2>의 char_ptr은 동작원리를 보여주기 위해서 간단하게 제작된 것이다. 실제 스마트 포인터의 구현은 훨씬 더 복잡하다. 하지만 걱정할 것 없다. 표준 라이브러이의 auto_ptr이나 boost 라이브러리의 shared_ptr과 같이 잘 구현된 스마트 포인터 클래스가 많이 있기 때문이다. 리스트 1 스마트 포인터를 사용하지 않은 코드 [CPP]void func() { char *ptr = new char[20]; if(some_condition) return; delete [] ptr; }[/CPP]리스트 2 스마트 포인터를 사용한 코드 [CPP]class char_ptr { private: char *m_ptr; public: char_ptr(size_t size) { m_ptr = new char[size]; } ~char_ptr() { delete [] m_ptr; } operator char *() { return m_ptr; } }; void func() { char_ptr ptr(20); if(some_condition) return; }[/CPP] |