공룡호가 사는 세상 이야기

<오류 소스코드>
#include
using namespace std;

class node
{
public:
int data;
node *next;
};

node head;
node tail;


void init_list(void)
{
*head = new node;
*tail = new node;

head->next = tail;
}

node* find_node(int key)
{
node *s;
s = head->next;
.
.
.
}

key값과 포인터를 갖는 구조체나 클래스를 정의한 다음,
node head, tail; 로 객체를 생성한다.

객체를 생성한 다음 초기화 하는 함수에서
접근이 가능하도록 포인터를 설정하고, new연산자로 공간을 할당한다.

하지만 저렇게 하였을 경우에는 심각한 에러를 발생시킨다.
다시 소스를 차근차근히 살펴보면, find_node 함수나 기타 함수 또는 어디서든 head나 tail에 접근할 수 없다.

이를테면 head에 접근하기 위해서는 *head로 접근을 시도해야 하는데, 해당 포인터를 init_list()함수 내에서 선언 해 버렸기 때문에, 함수가 종료되는 동시에 사라진다.(포인터변수 또한 변수임은 마찬가지)

그리하여, 다른 곳에서 head와 tail에 접근할 수 없을 뿐더러, 더욱 심각한 문제는 init_list()함수에서 선언했던 포인터변수는 사라지지만 new연산자로 할당한 2개의 공간(node)은 그대로 메모리를 차지한채 접근할 수 없는 상태로 허공을 떠돌게 된다.(메모리 누수)

그러므로 메모리할당은 함수 안에서 하되, head와 tail의 포인터 변수는 전역으로 설정해 주어야 한다.

node *head, *tail; // 전역

void init_list(void)
{
head = new node; // 함수가 종료되어도 사라지지 않는다.
tail = new node;
}

그리고 또한가지 그냥 지나칠 수 없는 점은
head와 tail의 연결 상태이다.원소가 아무것도 없는 리스트를 초기화 하고자 하여,
head->next = tail; 만 설정해 주게 되면 언뜻 아무 문제가 없어보인다.
하지만, while문 같은 루프의 내부에서 t=t->next;와 같은 문장이 있어서 계속 다음 노드로 이동하는 경우에 프로그래머의 실수로 루프를 끝내지 못할 경우 tail에 까지 이르게 되는데, 이 tail이 가르키는 곳을 정해주지 않아서 NULL이나 기타 엉뚱한 곳을 가르키고 있다면 t는 숨어버린다. 즉 다시 찾을 수 없다는 말이 된다.

이러한 결과는 결국 시스템이 다운을 가져온다. 대신에,
tail->next = tail; 이라는 한줄을 삽입하여, 꼬리 다음은 꼬리라고 순환적인 구조를 해 둘 경우 다운은 되지 않고 무한루프에 빠지게 된다.

무한루프는 Ctrl-Break로 멈출 수 있으며 디버그의 기능을 이용하여 현재의 상태를 점검해 볼 수 있다.
첨부파일 #1
첨부파일 #2

'프로그래밍' 카테고리의 다른 글

아파트 단지 번호 붙이기  (0) 2006.01.07
ACM 로마숫자 문제 변형판  (0) 2006.01.07
초점의 원리  (0) 2006.01.06
입력과 동시에 스트림에서 문자 가져오기 - getch();  (0) 2006.01.01
객체지향의 철학  (0) 2004.11.21