C/C++ 프로그래밍에서 포인터를 사용할 때 주의하지 않으면 치명적인 오류를 발생하게 된다. 포인터는 곧 ‘주소’이므로 어느 주소값을 가르키고 있는가가 가장 중요하다. 먼저 확인할 사항은 포인터가 초기화가 되었는가이다.
초기화되지 않은 포인터가 있을 경우 컴파일러에 따라 경고 메시지를 내기도 하고 경고 없이 실행하다가 실행 중 오류(runtime error)를 발생시켜서 프로그램이 다운될 수도 있다. 포인터를 사용할 때는 반드시 초기화를 시켜야 한다는 것을 알아두자.
다음 예를 보자
#include <stdio.h>int main(){double *dpa;*dpa = 1.0; //(1)} |
이 예는 언듯 문제가 없어보일 지도 모르지만 포인터 dpa가 초기화되지 않고 (1)에서 사용되었다. 이 프로그램은 컴파일러에 따라 컴파일시 오류를 발생하거나 실행이 되더라도 정상적인 동작을 하지 않고 프로그램이 죽어버릴 것이다. 그 이유는 포인터가 초기화되지 않은 상태이므로 정상적인 주소값을 가지고 있기 때문이다. 비정상적인 주소에 실수값 1.0을 대입하였으니 프로그램이 죽어버리는 것이다.
포인터를 초기화시키려면 다음과 같이 기존 변수의 주소값을 사용하는 방법이 있다.
#include <stdio.h>int main(){double da = 0.0;double *dpa = &da; // 변수 da의 주소로 포인터 dpa를 초기화*dpa = 1.0;} |
아니면 malloc()함수를 사용하여 정상적인 메모리 공간에 새로운 저장 공간(메모리)과 주소를 할당받을 수 있다.
#include <stdio.h>int main(){double *dpa = malloc(sizeof(double)); //새로운 저장공간과 주소값 할당*dpa = 10;…free(dpa); // 다 사용한 후 반드시 저장공간을 반환해야 한다.} |
malloc()함수와 free()함수는 stdio.h 헤더파일에 정의된 표준 함수이며 각각 메모리를 할당하고 반환하는 역할을 한다. sizeof()함수는 입력 인자의 바이트수를 반환하는데 sizeof(double) 은 double형의 바이트 수를 반환한다. (이 경우는 8) 따라서 8바이트 저장 공간을 확보한 후 그 주소를 반환한다. 그 주소는 포인터 dpa에 저장된다. 단, malloc()함수로 할당받은 저장 공간은 반드시 free()함수로 반환시켜야 한다.
다음 예를 보자. 다음 예는 ①에서 func(ipa)라고 호출을 하고 있다. 이 함수 내에서 포인터는 ②에서 내부 지역변수 ia의 주소값으로 초기화 된다. 그런데 func()함수 내부의 ipb포인터는 main()함수의 ipa와는 별개의 포인터이다. 따라서 main()함수 안의 ipa는 여전히 초기화가 되지 않은 포인터이다. 따라서 엉뚱한 값이 나오거나 프로그램이 실행 중지되기도 한다.
#include <stdio.h>void func(int*);int main(){int *ipa;func(ipa); //①printf("*ipa = %d\n in main()", *ipa);}void func(int *ipb){int ia = 20;ipb = &ia; //②printf("*ipb = %d in func().\n", *ipb);} |
다음 예는 소위 dangling 포인터의 예이다.
#include <stdio.h>void func(int*);int main(){int ia=10, *ipa = &ia;printf("*ipa = %d\n", *ipa);if (ia==10) {int ib = 20;ipa = &ib;}printf("*ipa = %d\n", *ipa);} |
if 블록 안에서 ipa가 &ib로 초기화가 되었지만 이 블록에서 벗어나는 순간 내부 변수 ib는 소멸되므로 ipa포인터도 그 소재가 불분명하게 된다. 이러한 경우를 dangling 포인터라고 하는데 프로그램이 길어질 경우 프로그래머가 의식하지 못하는 부분에서 이러한 실수가 일어날 수도 있게 된다. 당연히 이러한 경우도 방지해야 한다.
C++ 강좌 전체 목록 >>>
댓글 없음:
댓글 쓰기