11. 동적 할당
1. 동적 할당
메모리 동적 할당이란, 메모리를 할당하는 과정이 빌드 과정이 아닌 런타임(실행시간) 도중에 이루어지는 것을 말한다.
일반적인 메모리 할당은 프로그램이 빌드될 때 사용될 메모리의 크기를 고려하여 미리 할당이 이루어진다. 이는 스택 공간에서 이루어지며, 정적 메모리 할당이라고도 한다.
메모리 영역 | 사용 용도 |
---|---|
스택 영역 | 함수 및 지역 변수를 정해진 크기만큼 사전에 할당 |
데이터 영역 | 프로세스 시작 및 종료 시 사용, 전역변수, 정적변수, 외부변수 등이 사전에 할당됨 |
힙 영역 | 프로그램 런타임 도중 메모리 할당, 동적 할당에 사용됨 |
ROM(Read-Only Memory) | 전역 변수의 초기화 데이터, 문자열 데이터, 코드 등이 포함됨 |
동적 할당은 이전까지 설명한 함수나 지역/전역/정적/외부 변수들과 달리 힙 영역이라는 다른 메모리 영역을 사용하며, 런타임 도중 할당할 크기를 받아서 메모리 공간의 할당이 이루어지므로 포인터를 통해 사용하게 된다.
또한, 정적 할당과는 달리 프로그램이 자동으로 메모리 공간을 해제시켜주지 않으므로, 반드시 사용자가 메모리 공간을 별도로 해제시켜야 한다.
-
메모리의 할당과 해제
메모리의 할당 및 해제는 다음과 같은 함수를 호출함으로써 이루어진다:
메모리 할당 | 메모리 해제 | 사용 용도 | 인자 |
---|---|---|---|
malloc(_size) | free(_block) | 동적 메모리 할당 | _size: 힙에 할당 될 메모리의 크기(바이트) _block: 할당 된 메모리 블록 |
calloc(_count, _size) | 동적 메모리 할당과 동시에 0으로 초기화 | free(_block) | _count: 메모리에 할당 할 요소 개수 _size: 요소의 크기(바이트) _block: 할당 된 메모리 블록 |
realloc(_block, _size) | free(_block) | malloc/calloc으로 할당 된 메모리 재할당 | _block: 할당 된 메모리 블록 _size: 힙에 할당 될 메모리의 크기(바이트) |
new | delete(array의 경우 delete[]) | 동적 메모리 할당, class 에서 생성자가 호출됨 | (키워드이다) |
-
허상 포인터 (Dangling Pointer)
메모리의 객체를 해제시키면, 그 메모리를 할당했을 때 메모리의 시작 주소를 저장한 포인터는 해제된 메모리의 시작 주소를 가리키고 있는데, 이를 허상 포인터 (Dangling Pointer) 이라고 한다.
#include <iostream>
int main() {
int* ptr = (int*)malloc(40);
free(ptr); //메모리가 해제되며 ptr은 허상 포인터가 된다.
*ptr = 10; //해제된 메모리에 의도하지 않은 값이 할당된다.
return 0;
}
이 경우처럼 메모리를 해제한 후 의도하지 않은 값이 할당되거나 참조될 수 있으므로 Null 포인터로 초기화가 필요하다.
Null 포인터로 초기화될 경우, 이후에 해당 포인터에 값 할당을 시도하면 디버그 과정에서 오류가 발생하므로 포인터 문제를 사전에 발견할 수 있다.
-
힙 손상 (Heap Corruption)
힙 손상 (Heap Corruption) 오류는 힙 메모리 영역에 할당하지 않은 곳 까지 접근하거나 데이터를 참조하려고 할 때 또는 힙 오버플로우가 일어난 메모리의 해제가 이루어질 때 발생한다.
int* pData = (int*) malloc(20);
pData[0] = 10;
pData[1] = 20;
pData[2] = 30;
pData[3] = 40;
pData[4] = 50;
pData[5] = 60; //힙 오버플로우: 할당된 공간을 넘어서 접근하여 데이터 할당
free(pData); //힙 손상 오류 발생
-
메모리 누수 (Memory Leak)
동적 메모리의 할당 이후 메모리의 해제 과정이 이루어지지 않았을 경우(free 또는 delete 가 호출되지 않은 경우) 해제되지 않은 메모리가 힙 메모리 영역의 공간을 차지하고 있게 되는데, 이를 메모리 누수 (Memory Leak) 라고 한다.