티스토리 뷰

C++ 포인터

C++를 오며 포인터에 대한 많은 불편한 사항이 개선되었다. 그러면 무엇이 그렇게 잘못 되었기에 개선 사항들이 생긴 것일까?
 
이번 페이지에서는 포인터의 문제점 몇가지를 확인하고 가자.
 


동적 할당의 주의점

void function(){
	int* a;
    
    a = (int*)malloc(sizeof(int*));
    
    *a = 10;
    cout << *a << endl;
    
    free(a);
    
    *a = 5;
    cout << *a << endl;
}
10
5

 
위와 같은 함수가 존재할 때, 뭔가 이상한 부분이 보일 것이다.
분명 a에 malloc을 통해 동적 할당을하고 free를 통해 동적 할당을 해제하였다. 그런데 해당 코드는 아무런 이상 없이 동작한다. 이는 다음 그림과 같이 동작하기 때문이다.
 

 
그림 1. 포인터의 메모리 할당
 
그림1을 보면 스택 프레임에 생성된 포인터가 어떻게 값을 저장하는지 알 수 있다. 그런데 마지막 단계를 보면 분명 제거되었던 메모리 영역에 값을 또 저장하고 있다.
 
이는 포인터가 할당 받은 메모리 영역은 해제하였지만, 포인터가 가르키고 있는 메모리 주소의 위치 정보는 그대로 포인터에 남아있기 때문이다.
 
이로인해 발생할 수 있는 문제는 다음과 같다.
 

  • free()를 통해 시스템은 'a'의 힙메모리 주소가 할당 해제되었다고 생각한다.
  • free() 이후, 'a'라는 포인터가 값을 넣어버리면 시스템이 인식하지 못한 값이 입력된다.
  • 최악의 경우, function()함수가 종료되어 스택에서 제거 되었다면, 'a'라는 변수조차 사라져버려 '5'라는 값을 접근할 수도 없게된다. (강제로 메모리 주소에 접근하지 않는 이상)
  • 이후, 힙영역에 데이터들이 할당될 때, '5'가 들어있는 메모리 영역과 겹친다면 값이 변조되어 버린다.

 

해결법

위와 같은 상황을 해결하는 방법은 굉장히 간단하다.
바로 메모리 할당을 해제하고 포인터 변수도 nullptr로 지정해주면 된다.

void function(){
	int* a;
    
    a = (int*)malloc(sizeof(int*));
    
    *a = 10;
    cout << *a << endl;
    
    free(a);
    a = nullptr;
    
    *a = 5; // 오류
    cout << *a << endl;
}

 
 

포인터와 주소 접근

포인터는 또 하나의 특징이있다. 바로 연산자를 통해 여러 포인터에 접근이 가능하다는 것이다.
 
간략하게 말하면, 포인터는 연산자를 통해 시작 주소에서 다음/이전 주소로 옮겨다닐 수 있다.
이는 안정적이지 않은 주소값 처리이다. 만약, 연산을 통해 이동하고 다시 돌아오지 못한다면, 원래 사용하던 값은 쓰레기값이 되어버리기 때문이다.
 
C에서는 문자열의 경우, char*로 연산자를 사용하여 문자를 저장하고 읽어오기도 하였다. 하지만 C++로 넘어오며 든 컨테이너들이 반복자(iterator)라는 기능이 포함되기에 사실상 포인터를 통한 접근 자체를 권장하지 않는다.
 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함