동적 할당

-> 메모리 영역 중 Heap 영역에 저장된다.

-> 사용자가 원할때 메모리에 등록시키고, 사용자가 원할때 메모리에서 해제할 수 있다.

-> 단, 동적 할당한 메모리를 해제하지 않을 경우 메모리 누수가 발생한다.

-> 프로그램을 종료해도 메모리에 계속해서 상주한다.

-> 동적 할당은 C방식과 C++방식으로 나눠진다.

 

C 기반 동적 할당

char*	pName = nullptr;
pName = Func();
cout << pName << endl;

pName은 Func함수가 반환하는 값을 저장한다.

-> Func함수에는 szBuff라는 지역 변수가 있다.

-> Func함수가 반환하는 값은 해당 지역 변수의 할당 주소이다.

-> Func함수가 종료되면 stack 영역을 정리하면서 지역 변수의 할당 메모리 영역을 소멸시킨다.

-> 결과적으로 pName은 소멸될 공간의 주소를 받아오는 상황이다.

 

동적 할당 방법

#1 malloc()

-> void* : 시작 주소를 반환한다.

-> 단, 해당 시작 주소는 몇 바이트만큼 어떤 형식으로 읽을지 모르는 상황이다.

-> 이를 정상적으로 사용하기 위해서는 형 변환을 진행해야 한다.

malloc 함수를 선언하고 마우스를 올려보면 (size_t Size)가 보인다.

size_t _Size는 Heap 영역에 얼마만큼 메모리 공간을 할당할지 byte단위로 크기를 전달한다.

 

malloc(4)라고 선언하면 Heap 영역에 4byte만큼 공간을 할당한다는 의미이다.

 

malloc 함수 형 변환

(int*)malloc(4);

-> 할당한 공간의 주소를 반환할 때 int*형으로 형 변환해서 반환

 

int* ptr = (int*)malloc(4);

cout << "ptr: " << ptr << endl;		// Heap 영역의 주소
cout << "*ptr: " << *ptr << endl;	// heap 영역의 주소에 할당한 값

Heap영역에 4bytes만큼 할당 후 해당 공간의 시작 주소를 반환하는데,
int*형으로 변환하여 ptr이라는 변수에 저장한다.

 

동적할당 해제 

-> 동적할당을 해제 할 때는 free() 함수를 사용하면 된다.

그런데 동적할당을 해제 했음에도 주소 값이 그대로 있다.

-> 이유는 동적 할당된 메모리를 해제는 완료하였지만 주소 값은 그대로 남아있는 상황이 발생해서 그렇다.

-> 이것을 Dangling Pointer라고 한다.

 

Dangling Pointer(위험한 주소)

-> 동적할당을 해제한다해도 변수의 주소는 그대로 남아 있다.

 

Dangling Pointer가 발생하는 경우.

-> #1 할당되지 않은 메모리 공간의 접근

-> #2 다른 변수에서 동적할당한 곳이 같은 곳을 할당 받을 경우

 

Dangling Pointer 예방 방법

-> free 함수를 호출 후 변수를 nullptr로 초기화하는 습관을 들여야한다.

calloc()
-> size_t _Count : 몇 개를 할당할 것인지 전달.
-> 동적 배열을 만들 때 사용한다.

 

4bytes 공간을 3개 할당(동적 배열) 

calloc(3, 4); 

calloc으로 동적 배열 만들기

 

int iSize = 0;

cin >> iSize;

int*	pArr = (int*)calloc(iSize, sizeof(int));

for (int i = 0; i < iSize; ++i)
	cout << pArr[i] << endl;

malloc으로 동적 배열 만들기

int iSize = 0;

cin >> iSize;

int*	pArr = (int*)malloc(sizeof(int) * iSize);

for (int i = 0; i < iSize; ++i)
		cout << pArr[i] << endl;

malloc과 calloc의 차이점
-> malloc은 쓰레기 값으로 초기화
-> calloc은 0으로 초기화가 진행된다.

 

지금까지 한 것은 C기반의 동적 할당이고,

이번에는 C++기반의 동적할당을 해보자.

 

C++ 기반의 동적 할당

new 연산자

사용 예)

new 자료형

int* ptr = new int;

Heap 영역에 자료형의 크기만큼 공간을 할당하고,

자료형의 포인터형으로 주소를 형 변환하여 반환한다.

 

동적 할당 해제

delete

delete ptr;
ptr = nullptr

C기반은 포인터를 초기화 하지 않고 동적 할당을 해제하면 주소 값이 그대로 남지만,

C++ 기반은 다른 곳에서 동적 할당할 경우에 같은 주소를 참조하지 않게 다른 곳으로 주소가 바뀐다.

이 경우 역참조를 이용하여 데이터를 다룰 경우 오류가 발생한다.

 

C++ 기반 역시 Dangling Pointer 때문에 동적 할당을 해제하고나서 포인터를 nullptr로 초기화 해줘야 한다.

 

동적할당과 동시에 초기화

-> C++ 기반은 동적 할당과 동시에 초기화가 가능하다.

int* ptr = new int(10);

C기반의 초기화

int a = 10;

C++기반의 초기화

int a(10);

 

C++기반의 동적 배열

int iSize = 0;
cin >> iSize;

int* ptr = new int[iSize];

동적 배열 해제 방법

ptr 변수로만은 Heap 영역에 할당된 공간이 배열인지 아닌지 알 수 없는 상황이다.
-> 컴파일러는 단순하게 자료형을 토대로 판단한다.

// 주소만 남기고 삭제
delete
ptr = nullptr;

// 전체 삭제
delete[] 
ptr = nullptr;

// 동적 배열 삭제
delete[] (ptr);
ptr = nullptr;

 

모든 메모리 할당은 직접 구현한 New, Delete 키워드를 통해 호출하는 것이 좋다.

'Programming > C++ Basic' 카테고리의 다른 글

C++ 경로  (0) 2020.09.02
C++ 입출력 스트림 버퍼, 단일 문자 입/출력 함수  (0) 2020.09.02
C++ 구조체와 포인터  (0) 2020.08.31
C++ 구조체(Struct)  (0) 2020.08.31
C++ 문자열 함수  (0) 2020.08.31

+ Recent posts