2023. 1. 6. 23:21ㆍ자료구조, 알고리즘
해당 내용은 자료구조/알고리즘을 공부하기 위해 작성된 것입니다.
혹시 오류가 있다면 지적 부탁드립니다.
정적 메모리와 동적 메모리
프로그램에서 사용하는 변수들은 자료형에 맞는 메모리를 할당받게 됩니다.
이 메모리들은 정적 메모리 또는 동적 메모리라는 이름으로 존재합니다.
먼저 정적 메모리란 코딩 과정에서 변수에 할당할 메모리를 미리 지정해 주는 방식이며, 이 메모리는 프로그램이 끝날 때까지 크기가 변경되지 않고, 프로그램이 끝날 때만 자동으로 사라지게 되는 메모리입니다.
정적 메모리들은 다음과 같습니다.
int a = 10;
int array[100];
char *str = "data structure"
정적 메모리들은 대체로 우리가 자주 사용하는 변수 선언과 같다고 볼 수 있으며, 간단히 작성할 수 있습니다.
그러나 정적 메모리 할당 방식은 메모리를 미리 지정해 주는 방식이므로
지정한 메모리보다 큰 데이터가 들어온다면 그것들을 모두 처리하지 못하며,
메모리보다 현저히 작은 데이터가 들어온다면 메모리 낭비가 발생할 수 있습니다.
동적 메모리는 반대로 프로그램 실행 중에 필요한 메모리의 크기를 결정하고 여기에 맞는 메모리를 할당받는 방식입니다.
필요한 만큼만 할당받는 방식이므로 정적 메모리에 비해 메모리가 부족하거나 낭비되는 경우를 방지할 수 있습니다.
대신 정적 메모리와는 달리 사용 후에는 개발자가 메모리를 직접 해제해 주어야 한다는 단점이 있습니다.
동적 메모리의 예시는 다음과 같습니다(출처 : C++로 쉽게 풀어쓴 자료구조(2016, 생능출판)).
int main()
{
int x; // 정적으로 int 객체 할당
int* py = new int; // 동적으로 int 객체 할당
x = 10;
*py = 20;
delete py; // 동적으로 int 객체 제거
int arrA[20]; // 정적으로 배열 할당
int* arrB = new int[20]; // 동적으로 배열 할당
arrA[3] = 10; // 정적 배열의 사용
arrB[3] = 20; // 동적 배열의 사용
delete[] arrB; // 동적으로 배열 제거
// 정적 객체(x, arrA) 자동 해제
}
동적 메모리 할당과 해제
앞서 언급하였듯, 동적 메모리를 할당하게 되면 메모리 사용 이후 반드시 사용자가 메모리를 해제해 주어야 합니다.
그러므로 새로운 메모리를 할당하는 함수와 사용한 메모리를 해제하는 함수를 모두 알아야 합니다.
1) malloc()와 free() : C 언어
C 언어에서 제공하는 함수로는 malloc()와 free()가 있으며, malloc()는 메모리를 할당할 때, free()는 메모리를 해제할 때 사용하는 함수입니다.
malloc()와 free()를 사용하여 메모리를 할당 및 해제하는 예시는 다음과 같습니다.
# include <stdlib.h> // malloc() 함수를 사용하기 위해 선언
int *pi; // 정수 포인터(배열) 선언
pi = (int *)malloc(10 * sizeof(int)); // 정수를 10개 저장할 수 있는 동적 메모리(공간) 할당
free(pi); // 동적 메모리 반납
double* pd; // 실수 포인터(배열) 선언
pd = (double *)malloc(20 * sizeof(double)); //실수를 20개 저장할 수 있는 동적 메모리(공간) 할당
free(pd); // 동적 메모리 반납
먼저, 포인터(배열)을 선언합니다.
이후 해당 배열에 필요한 메모리를 할당하기 위해 malloc() 함수를 사용합니다.
malloc() 함수 부분은 좀 더 자세히 보면,
- malloc() 함수는 기본적으로 *void 형이므로, (int*)나 (double*) 등 원하는 자료형으로 형 변환을 해줍니다.
- malloc() 안에 있는 sizeof() 함수는 자료형의 크기를 구하는 함수입니다. int형은 4바이트이므로 sizeof(int)는 4가 되며, double형은 8바이트이므로 sizeof(double)은 8이 됩니다.
- 여기에 배열에 들어갈 값의 개수를 곱합니다. *pi의 경우 10개의 정수값이 들어가므로 sizeof(int)에 10을 곱하고, *pd에는 20개의 실수값이 들어가므로 sizeof(double)에 20을 곱하게 되는 것입니다. 그렇게 되면 자료형의 크기(바이트) x 값 개수로서 배열에 필요한 메모리가 할당되는 것입니다.
malloc()를 이용한 메모리 할당은 모두 끝났으며, 사용 후 할당된 메모리는 모두 해제해주어야 하므로 free()를 사용합니다.
free()의 사용법은 malloc()에 비해 간단합니다. 해제할 포인터 변수를 free() 안에 입력하면 끝나게 됩니다.
2) new와 delete : C++에서 새로 추가된 연산자
C가 c++로 넘어오면서 malloc()와 free()의 역할은 new와 delete 연산자가 대신 수행합니다.
new와 delete의 사용 예시는 다음과 같습니다.
int *pi = new int; // int형 메모리 1개 할당
char *pc = new char[100]; // char형 메모리 100개 할당
delete pi; // int형 메모리 해제
delete pc[]; // char형 메모리 해제
malloc() 함수에서는 배열의 자료형을 일일히 지정해 주어야 했지만, new를 사용하면 포인터를 선언함과 동시에 간단하게 메모리를 할당할 수 있습니다.
만약 1개의 자료를 담는다고 하면 "new 자료형"으로 작성하며, 2개 이상의 자료를 담는 배열이라면 자료형 뒤에 "[자료 개수]"를 입력합니다.
new를 사용하여 메모리를 할당하였으니, 이제는 delete를 사용하여 메모리를 해제해 봅시다.
메모리 해제는 delete에 포인터 변수명을 입력함으로써 간단히 수행할 수 있습니다.
다만 하나의 자료를 담았을 경우 단순히 변수명만 입력하면 되나, 2개 이상의 자료를 담았던 배열이라면 변수명 뒤에 "[]"를 붙여 여러 개의 자료가 한꺼번에 해제할 수 있도록 합니다.
참고자료
1. 신윤환(2021), C 언어 일취월장, 한빛아카데미
2. 천인국, 최영규(2016), C++로 쉽게 풀어쓴 자료구조, 생능출판
'자료구조, 알고리즘' 카테고리의 다른 글
| 05. 포인터 (4) | 2022.12.30 |
|---|---|
| 04. 클래스 (4) | 2022.12.22 |
| 03. 배열 (2) | 2022.12.03 |
| 02. 알고리즘 시간 복잡도 함수(2) (1) | 2022.11.24 |
| 02. 알고리즘 시간 복잡도 함수(1) (6) | 2022.11.16 |