반응형

0. 시작하기

 

 

1. New 키워드에 대해서

앞에서 동적할당에 대해서 간단하게 말씀드렸습니다. 여기서는 메모리와 연결해서 조금 더 자세하게 알아보도록 하겠습니다.

 

int *pt = new int[10];

위의 간단한 코드를 메모리측에서 보면 Heap영역과 Stack영역을 나눠서 봐야합니다.

 

앞서 다른 게시물에서 언급했듯 Heap영역은 동적할당시 사용되는 메모리 영역이며, Stack영역은 지역변수(변수,포인터, 참조자 등 모두해당됩니다.)가 사용하는 메모리 영역입니다.

 

따라서 위의 과정을 메모리 영역에서 보면 아래와 같은 모습을 볼 수 있습니다.

 

 

int *pt = new int[10] 에 대한 메모리 추상화

 

new int[10] 이라는 코드가 heap영역에 공간을 확보하고 해당 공간의 주소값을 반환한다고 했는데, 확인해보겠습니다.

 

#include <iostream>
using namespace std;

int main(void){
    cout << (new int[10]) << endl;

    return 0;
}

실행결과

 

 

위와같이 new 키워드의 결과를 출력하면 주소값을 반환하는 것을 볼 수 있습니다. 때문에 주소값을 저장하기 위해 포인터(*)를 사용하는 것입니다.

 

위에서 heap영역과 stack영역을 구분해서 말씀드린 이유가 있습니다!!

 

가장 중요한 이유, 그것은 stack영역에 저장되는 데이터는 함수가 종료되는 시점까지만 유효한 값을 갖습니다.(지역변수) 반면 heap영역은 할당받은 메모리를 반환할때까지 유효한 값을 유지합니다.

 

이에대한 두가지 예제를 보겠습니다.

 

첫번째는 stack 영역에 저장된 값의 주소를 반환한 경우입니다.

 

#include <iostream>
using namespace std;

int* func(){
    int x=10;
    return &x;
}


int main(void){
    int *pt = func();
    cout << *pt << " : " << pt << endl;

    return 0;
}

경고 메시지
실행결과

 

해당 코드를 실행하면 위와같은 [경고메시지]와 [실행결과]를 볼 수 있습니다.

 

다음으로는 heap 영역에 저장된 값의 주소를 반환하는 경우입니다.

 

#include <iostream>
using namespace std;

int* func(){
    int *x = new int;
    *x = 10;
    return x;
}


int main(void){
    int *pt = func();
    cout << *pt << " : " << pt << endl;

    return 0;
}

실행결과

 

후자에서는 [경고메시지]없이 [실행결과]를 얻을 수 있었습니다.

 

의문이 들 수 있습니다. [경고메시지가 출력되기는 했지만, 실행만 잘 되면 괜찮은거 아닌가요?] 라는 의문.

 

답은 절대로 안됩니다!

 

 

 

여러분이 프로그램을 설계할 때, 심심하면 한번씩 이상한 값을 출력하길 원하는게 아니라면, 절대 위와같은 경고메시지(⚠️)를 무시하시면 안됩니다.

 

위의 경고메시지가 발생하는 원인은 한가지 입니다.

 

-> 유요하지 않은 값, 즉 해당 메모리는 다른 값에 의해서 언제든지 덮에 씌워질 수 있는 상태라는 것입니다.

 

새로운 값이 스택영역에 저장되면 해당 공간에는 다른 값이 저장되고, 그때는 10이 아닌 다른 값을 출력할 것입니다. [경고메시지]의 출력을 제거한 상태라면 위와같은 문제로 프로그램이 꼬였을 때, 문제를 찾기도 힘들죠.

 

반면 후자에서 사용한 heap영역의 주소를 반환했을 때에는 함수가 종료된 후에도 [heap 영역의 데이터] 가 유효한 상태를 유지하기 때문입니다. heap영역의 데이터는 프로그램이 종료되거나, 해당 공간을 os에 반환할 때까지 유효한 값을 갖습니다.

 

 

 

OS로부터 할당받은 공간을 사용 후 반환, 그리고 다시 해당 값을 참조하는 것은?

 

이건 더 큰 문제를 야기할 수 있습니다. heap영역은 가변가능한 공간입니다. 사용하지 않을경우 OS에 반환(또는 회수)되는 공간이죠.

 

이렇게 반환된 공간은 다른 프로그램에 의해서 사용될 수 있습니다.

 

운이 나쁘다면(?) 반환된 공간을 참조함에따라 다른 프로그램이 사용중인 영역의 값을 프로그램이 요청하게되고, 이것은 운영체제의 프로세스 관리 규칙에 위배됨에따라 강제로 해당 프로그램이 종료되는 문제를 발생시킬 수 있습니다.

 

 

 

2. Delete 키워드에 대해서

사실 New 키워드에 대해서 자세히 다룬 덕분에 delete에 대해서는 크게 말씀드리게 없습니다.

 

단일 객체에 대한 할당을 제거할 시 delete를 사용하고, 배열 객체에 대한 할당 제서기 delete[]를 사용한다는 차이와 delete를 사용한 후에도 해당 영역에 대한 참조가 가능하지만, 실제로 접근하면 new키워드의 마지만 부분에서 언급했던 문제와 같은 일이 생길 수 있다는 것만 말씀드리면 될 듯합니다.

 

 

 


...더보기

해당내용은 사용하는 운영체제(OS)와 컴파일러, IDE에 따라서 차이가 있을 수 있는 내용입니다.

반응형

+ Recent posts