리스트 노드해제
조회수 689회
클래스와 구조체를 이용해서 리스트를 흉내 봤는데요 노드를 해제할때 밑에 있는 코드만 있으면 힙영역에 있는것들이 모두 해제 되나요?
일단 코드의 일부만 복사 했는데 이 코드들로만 판단이 안되면 다시 올릴게요 (class CIntList에 노드의 시작주소와 데이터값을 저장하는 변수를 2개 선언했어요, 그리고 구조체 노드에는 다음 노드의 주소와 데이터값을 저장하는 변수를 2개 선언했어요)
~tNode()
{
if (NULL != pNext)
{
delete pNext;
}
}
CIntList::~CIntList()
{
if (NULL != m_pHead)
{
delete m_pHead;
}
}
1 답변
-
단일 연결 리스트를 말씀하시는 건가요? 현재 아마 작은 단위의 데이터는 상관없이 모두 해제될 겁니다.
1) 이렇게 아래처럼 적어주시고 디버깅하시면 디버깅 창 아웃풋에 memory leak이 있는지 알려줍니다. 혹시 모르니 본인 코드로 직접 해보세요.
#define _CRTDBG_MAP_ALLOC // 다른 헤더 파일 위, 아래에 넣어줍니다 #include <iostream> using std::cout; #include <stdlib.h> #include <crtdbg.h>
int main() { // 메인 함수 가장 위에 넣어줍니다. _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); // ... return 0; }
2) 자 근데, 지금 코드도 잘되는데 이 아래에 있는 길고 쓸데없어 보이는 코드는 뭔가요? 문제는 위에 '작은 단위의 데이터'라고 했듯이 지금 코드가 능률적이지 않고 불안정하다는 점에 있습니다.
지금 코드는 list 오브젝트가 해제되기 위해, 그 소멸자에서 노드 head 포인터를 삭제합니다. 그럼 그 노드는 소멸자를 부르고, 그 다음 노드를 삭제하는데 그러기 위해서 그 다음 노드의 소멸자를 부르고 그 다음 다음 노드를 지울려고 그 다음 다음 노드의 소멸자를 부르고...
여기서 문제는 가장 마지막 노드의 소멸자가 불려질 때 그 전 모든 노드의 소멸자 함수가 아직 열려있기 때문입니다. 소멸자는 스택 메모리를 사용하는데 모든 노드가 삭제될 때까지 메모리 사용은 늘어가기만 하고 줄어들지를 않습니다. 1000개 정도 크기의 데이터에서는 상관없겠지만, 그 크기가 10000, 100000개를 넘어가면 스택 메모리가 부족해서 에러가 날겁니다.
이걸 고치기 위해서 이런 재귀적 (반복적) 호출 방식을 피해, 각 노드를 리스트에서 직접 지워줍시다.
CIntList::~CIntList() { tNode * trail_node = nullptr; tNode * travel_node = m_pHead; while(travel_node != nullptr) { // 현재 travel_node (head 혹은 다음 노드)를 지우기 위해 // 복사본을 만들어줍니다. trail_node = travel_node; // 복사 후에 다음 노드로 넘어갑니다. travel_node = travel_node->m_pNext; // 아까 복사한걸 지워줍니다. delete trail_node; } // 값의 초기화 m_pHead = nullptr; }
이제 노드 소멸자에서는 다음 노드의 소멸자를 불러 삭제 delete 할 필요가 없습니다.
tNode::~tNode() { // 값의 초기화 m_pNext = nullptr; m_data = 0; }
-
(•́ ✖ •̀)
알 수 없는 사용자
-
댓글 입력