메모리관리


C/C++은 동적으로 할당한 메모리를 사용한 후 해제하지 않으면 '메모리 누수(Memory Leak)가 발생하여 시간이 지난 후 프로그램 실행에 큰 문제를 일으킨다. 작은 프로그램에서는 프로그래머가 실수 없이 할당과 해제를 잘하므로 메모리 누수가 거의 발생하지 않는다. 하지만 동적 메모리 할당을 자주 사용하고 코드가 복잡한 대형 프로젝트에서는 필연적으로 발생한다.


이런 문제를 해결하기 위해 C++11에서는 사용하지 않는 메모리를 자동으로 해제 시켜주는 'shared_ptr'와 'unique_ptr'라는 라이브러리가 새로 생겼다. 동적으로 할당한 메모리 해제를 자동으로 관리해주는 것을 '스마트 포인터(Smart Pointer'라고 하는데, shared_ptr와 unique_ptr가 이에 해당한다. 사실 C++03에도 같은 기능을하는 'auto_ptr'라는 것이 있지만, 제약이 있어서 거의 사용하지 않는다. shared_ptr와 unique_ptr은 auto_ptr의 문제를 해결한 스마트 포인터다.


스마트 포인터를 사용하면 성능 측면에서는 손해가 거의 없으면서도 메모리 관리의 편리함을 얻을 수 있으므로 C++11에서는 이것을 자주 사용하기 바란다.




shared_ptr





<shared_ptr 사용 예제>





shared_ptr이 관리하는 객체 사용


shared_ptr로 관리하는 객체의 포인터를 얻을 때는 'get()', 참조를 얻을 때는 operator '*', 인스턴스의 멤버에 접근할때는 operator '->'를 사용한다.


<shared_ptr이 관리하는 인스턴스 사용하기>






명시적으로 관리하는 객체 삭제 및 다른 객체로 바꾸기


shared_ptr의 reset() 멤버 함수를 사용하면 기존에 관리하던 객체를 다른 객체로 교체할 수 있다.(이때 기존 객체는 파괴된다.) 또한, reset() 멤버 함수에 인자값을 사용하지 않으면 명시적으로 객체를 파괴할 수 있다.


<reset()으로 관리하는 객체 삭제 및 바꾸기>







두 개의 shared_ptr끼리 서로의 객체 교환하기


STL의 vector 같은 컨테이너들은 swap을 사용하여 가지고 있는 요소를 교환하는데, shared_ptr 역시 swapt기능을 지원한다.


<swap()으로 교환하기>






배열 객체 다루기


많은 객체나 데이터를 다루다 보면 배열식으로 동적 할당을 해야 할 때가 자주 있다. shared_ptr도 당연히 배열로 할당한 것을 다룰 수 있다. 방법은 매우 간단하다. shared_ptr도 당연히 배열로 할당한 것을 다룰 수 있다. 방법은 매우 간단하다. shared_ptr을 생성할 때 삭제자(Deleter)를 사용하여 배열임을 알려주면 된다.


<배열 객체 다루기>






삭제자 지정하기


shared_ptr을 정의할 때 std::default_delete<Particle[]>로 삭제자를 지정했었다. 배열 할당을 해제하기 위해 기본 형식을 사용했느데 함수나 함수 객체를 삭제자로 등록하면 shared_ptr에서 관리하고 있는 메모리를 해제할 때 특정한 행동을 할 수 있다. 메모리 풀(Memory Pool)등을 사용할 때 아주 유용한 기능이다.


<삭제자 사용>






좀 더 간단하게 shared_ptr만들기







shared_ptr의 함정 순환 참조


shared_ptr을 사용하면 이전보다 메모리 관리가 쉬워지지만, 생각 없이 사용하면 큰 재앙이 일어날 수 있다. 재앙을 일으키는 원인중 하나가 '순환 참조'다. 순환 참조는 GC을 사용하는 다른 언어에서도 발생하는 문제로, 이것 때문에 이른바 메모리 누수가 발생한다.


<순환참조 유발 코드>







출처 : Thinking About C++ STL 프로그래밍 (최홍배 지음)



+ Recent posts