출하를 몇일 앞두고, 프로그램 전반적으로 메모리 누수가 발견됬다.

원인은, 객체를 동적 할당하여 이곳 저곳 벡터에 포인터 값을 넘겨 저장하고,

벡터의 멤버함수 close()를 호출하여 마무리 작업을 완료 하였기 때문. (당황스럽지만 실제 발생된 일이다.)

실수라고 보기엔 너무나도 어이없고 당황스러운일. 아무튼 문제를 빨리 해결하는게 급선무.

그럼 그냥 delete문만 추가해주면 되겠네?? 하지만 현실은 그리 호락호락 하지 않다.

동적 할당된 구조체의 주소를 이곳 저곳 벡터에서 동시에 사용 하다 보니, 어느 하나의 벡터의 요소들을

먼저 delete 해버리면, 다른 vector에 혹시라도 중복된 요소가 있을경우, 그 요소가 가리키는 메모리가

해제된걸 알지못하고 두번 delete하는 일이 발생하여 결국 프로그램 Down으로 이어진다.

그럼 어떻게 하냐고??


세가지 방안을 생각해봤다.

첫째, 동적 할당된 주소를 넘겨 처리하던 구조를 정적할당한 구조체 자체로 넘겨주는 구조로 변경한다.

이렇게 되면 해당 벡터의 요소를 참조하는 모든 부분의 접근 연산자를 '->' 에서 '.'으로 변경 해주어야 한다.

물론 이는 탐색 변경 기능으로 빠르게 수정 가능하다. 다만 메모리 사용률이 동적할당 주소값을 사용하던 시절보다

많아진다는 단점은 있었다.(당연히 동적 할당된 메모리를 처리하지 않아 누수되는것보단 백번 낫다)


둘째, 동적 할당된 주소들을 관리하는 로직을 추가한다. 이 방법을 사용 하면 첫째 방법에 비해 메모리 효율이 있고

지금의 구조는 그대로 유지 가능하나, 추가 로직을 구현하고 전반적으로 많은 테스트가 필요하다는것이 상당히

번거로우며 시간적 효율이 없어 보인다.


셋째, Boost 라이브러리의 Shared Pointer를 사용 한다. 이 방법을 사용 하면 동적 할당된 메모리의 해제를 직접

해줄 필요가 없다. 메모리를 참조하던 변수들의 개수가 0이 되는 순간(내부 참조 카운트를 가진다) 스스로를 delete

하는 아주 쓸모있는 포인터이다. 다만 한번도 써본적이 없어서 사용 방법을 익히고 동작 매커니즘을 이해해야 한다는

수고는 있다. (첫째 방법과 마찬가지로, 벡터 요소를 참조하는 모든 로직의 수정이 필요하다.)



자 어떤 방법을 사용 할까? 선택은 내 몫이다. 




*Shared Pointer : 동적 메모리의 주소값을 참조하는 변수들을 자체적으로 Count한다. 이를 레퍼런스 카운트라

하는데, 레퍼런스 카운트가 0이 되는 순간 스스로를 delete 시킨다. (즉 New가 있으나 Delete가 없는 광경)


*Weak Pointer : Shared Pointer가 스스로를 참조할경우 레퍼런스 카운트가 꼬이는? 현상을 방지하며, 해당

Shared Pointer가 가리키는 동적 메모리가 존재 하는지를 판별하는 용도로 사용 된다.(설명이 어렵다.)


*Smart Pointer : Pointer가 선언 범위를 넘어가는 순간 소멸자가 호출되고 소멸자 내에서 자기 자신의 동적 

메모리를 삭제 한다.

'직장 이야기' 카테고리의 다른 글

마지막 출근.  (0) 2016.12.30
이전 누군가의 코드를 유지 하려는 것.  (0) 2016.02.24
Posted by Yann'
,