상세 컨텐츠

본문 제목

[C++] 동적 메모리 할당

C++

by Wanderer Kim 2019. 8. 23. 20:41

본문

728x90

이번 시간에는 C++에서 동적 메모리 할당하는 방법에 대해 살펴보자.

동적 메모리 할당 방법을 보기 전에 동적 메모리 할당이란 무엇인가에 대해서 먼저 알아보겠다.

 

동적 메모리 할당의 개념

동적 메모리 할당이란 컴퓨터 프로그래밍에서 실행 시간동안 사용할 메모리 공간을 할당하는 것을 뜻한다. 사용이 끝나면 운영체제가 쓸 수 있도록 반납하고 다음에 요구가 오면 재할당을 받을 수 있다. 이것은 프로그램이 실행하는 순간 프로그램이 사용할 메모리 크기를 고려하여 메모리의 할당이 이루어지는 정적 메모리 할당(static memory allocation)과 대조적이다.

 

동적으로 할당된 메모리 공간은 프로그래머가 명시적으로 해재하거나 쓰레기 수집(garbage collection)이 일어나기 전까지 그대로 유지된다. C/C++의 경우 garbage collection을 자동으로 해주는 garbage collector가 없어 사용자가 수동으로 해제하기 전까지는 메모리 공간이 계속 유지된다. 반면에 java나 C#의 경우 garbage collector가 있어 사용자가 따로 동적 메모리 해제를 해줄 필요가 없다.

동적 할당은 프로세스의 힙영역에서 할당하므로 프로세스가 종료되면 운영 체제에 메모리 리소스가 반납된다. 그러나 프로세스가 계속 실행될 때에는 동적할당 된 영역은 유지되므로 프로그램이 정해진 힙 영역의 크기를 넘는 메모리 할당을 요구하면 할당되지 않는다. 따라서 사용이 완료된 영역은 반납하는 것이 유리한데, 만약 사용자가 메모리 해제를 따로 해주지않으면 프로세스가 메모리를 불필요하게 계속 점유하는 메모리 누수(memory leak)현상이 나타난다.

 

힙 영역

힙은 프로그래밍 환경에서 원시 자료형이 아닌 보다 큰 크기의 데이터를 담고자 동적으로 할당하는 메모리 공간을 지칭한다. 프로그램 코드에서 원하는 크기의 메모리 할당을 요청하면 힙을 관리하는 라이브러리 혹은 모듈이 지정된 크기의 힙 공간 안에서 사용 가능한 곳을 찾아 그곳을 다른 스레드나 프로그램이 사용하지 못하도록 예약 상태로 만들고 접근 가능한 핸들이나 포인터를 반환하는 식으로 사용할 수 있다.

 

물론 구조체나 객체를 스택에 선언하여 사용하는 것도 가능하지만, 싱핼 시간에 크기가 결정되는 동적 배열 및 리스트와 같은 경우는 힙을 사용하는 것이 보다 공간을 효율적으로 활용할 수 있다.

참고사항으로 아래에 메모리 맵 예제를 첨부한다.

메모리 맵 예

Notes:

  • 배치할 때 이름은 CPU와 컴파일러에 따라 다르다. 개발 도구를 선택하면 맵 파일이 필요할 경우 맵 파일을 만드는 방법이 옵션으로 존재하고, 메모리 맵 파일 생성 옵션을 설정하면 생성된다. 세크먼트는 컴파일러에 따라 더 세분화되어 관리될 수 있다. MCU의 경우 메모리 관리에서 전역 변수의 메모리 영역이 나뉘어 있을 수 있으므로, 이 섹터의 상태 등을 확인하고 개발자가 적당히 배치할 수 있다.

동적 메모리 할당과 해제를 위한 연산자

C++에서는 동적 메모리 할당과 해제를 위하여 new와 delete키워드를 제공한다.

 

new 연산자

new는 동적으로 메모리를 할당하여 주소를 반환하는 연산자로 다음과 같이 사용된다.


data_type *pData = new data_type;


위 문장에서 new는 data_type 크기의 메모리 블록을 할당하여 그 블록의 시작 주소(포인터)를 반환하는 연산자이다. 반환된 주소는 pData에 복사된다. 이때 data_type에는 int나 double같은 기본 자료형뿐 아니라 구조체나 클래스도 포함된다. 한편 new는 한꺼번에 여러 개의 객체를동적으로 할당하는 방법도 제공한다.


data_type *array = new data_type [size];


위 문장에서 size개의 data_type을 저장할 수 있는 연속된 메모리를 찾아 할당하고 그 메모리 블록의 시작 주소를 반환한다. 이 주소는 array 포인터 변수에 저장된다. 이것은 같은 자료형의 연속된 공간, 즉 배열을 할당하는 것을 의미하고, 따라서 각 요소에 대한 접근을 array[3]과 같이 일반적인 배열처럼 할 수 있다.

 

delete 연산자

delete는 동적으로 할당되었던 메모리 블록을 시스템에 반환한다. 앞에서 할당한 pData와 array에 대한 메모리 동적 해제 코드는 다음과 같다.


delete pData; // 하나의 객체로 할당된 메모리 해제

delete[] array; // []을 이용해 배열로 할당된 메모리 해제


동적 메모리 할당과 해제 예제

#include <iostream>

using namespace std;

int main()
{
	int* pData = new int; // 하나의 객체 형대로 동적 메모리 할당
	*pData = 10; // pData의 값을 10으로 할당
	cout << "pData: " << *pData << endl;
	delete pData; // 메모리 해제

	int* array = new int[5]; // int형 5개의 메모리 할당
	for (int i = 0; i < 5; i++) //  array의 각 인덱스에 값을 할당
	{
		array[i] = i * 10;
	}
	for (int i = 0; i < 5; i++)
	{
		cout << "array" << "[" << i << "]" << ": " << array[i] << endl;
	}
	delete[] array; // 여려개의 메모리 해제

	return 0;
}

 

반응형

댓글 영역