동적 메모리 할당이란 프로그램의 실행 도중에 메모리를 할당 받는 것입니다. 필요한 만큼만 할당을 받고 또 필요한 때에 사용하고 반납합니다. 이로 인해 메모리를 효율적으로 관리하고 사용이 가능합니다.
메모리 영역은 스택(Stack :: 지역변수, 매개변수), 힙(Heap :: 동적 할당), 데이터(Data :: 전역변수, static), 코드(Code, Text :: 코드, 함수, 제어문) 으로 이루어져 있는데 동적 할당의 경우 힙 영역에 저장됩니다.
main()
{
int *pi;
pi = (int *)malloc(sizeof(int)); // 동적 메모리 할당
// ...
// ... 동적 메모리 사용
// ...
free(pi); // 동적 메모리 반납
}
C에서 동적 메모리를 사용하는 함수로 malloc()을 사용합니다. C++에서는 new, vector 등이 있습니다.
동적 메모리를 받을 포인터 변수 pi를 선언하고 그 값으로 동적 메모리의 주소를 할당합니다. 위 코드에서 pi는 정수형 크기만큼의 공간을 할당받고 int 포인터로 형변환 하여 값을 할당하였습니다.
동적 메모리를 사용한 이후에는 반드시 free() 를 통해 메모리를 반납하도록 합니다. 사용하지 않아도 당장 프로그램에 문제는 없겠지만 프로그램이 커질 경우 메모리가 누수되는 문제가 발생합니다.
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define SIZE 10
int main(void)
{
int *p;
p = (int *)malloc(SIZE * sizeof(int));
if (p == NULL) {
fprintf(stderr, "동적 메모리 할당 실패\n");
exit(1);
}
for (int i = 0; i<SIZE; i++)
p[i] = i;
for (int i = 0; i<SIZE; i++)
printf("%d ", p[i]);
free(p);
return 0;
}
정수 10개를 저장할 수 있는 동적 메모리를 할당하고 free() 를 이용하여 메모리를 반납한 프로그램입니다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct studentTag {
char name[10]; // 이름
int age; // 나이
double gpa; // 평균평점
} student;
int main(void)
{
student *p;
p = (student *)malloc(sizeof(student));
if (p == NULL) {
fprintf(stderr, "동적 메모리 할당 실패\n");
exit(1);
}
strcpy(p->name, "Park");
p->age = 20;
p->gpa = 77;
free(p);
return 0;
}
구조체 메모리를 동적 할당한 프로그램입니다.
이제 문제를 통해 동적메모리의 할당과 반납을 정리해봅시다.
[1-1] 다음 프로그램의 오류를 모두 찾아내고 수정하라.
// 오류가 있는 프로그램입니다.
int main(void)
{
double *p;
p = (int *)malloc(double);
p = 23.92;
}
// 오류가 있는 프로그램입니다.
더보기
>> 이 프로그램은 포인터p가 double형으로 선언되어 있으나 p에 동적 메모리를 할당하는 과정에서 메모리의 크기를 구체적으로 입력하지 않고 자료형의 이름만 입력한 문제점(1)과 형변환을 double형으로 하지 않고 int형으로 변환한 문제점(2), 포인터p가 할당받은 메모리 공간에 값을 할당하는 과정에서 p를 역참조하지 않고 포인터 변수에 직접 값을 할당하려하는 문제점(3)이 있다.
문제 해결
int main(void)
{
double* p;
p = (double*)malloc(sizeof(double));
if (p == NULL) {
fprintf(stderr, "동적메모리 할당 실패\n");
exit(1);
}
*p = 23.92;
free(p);
return 0;
}
더보기
>> 포인터p의 메모리 크기를 double 자료형의 사이즈 8byte로 수정하였고 double형 포인터로 형변환하였으며 값을 할당하는 경우 p를 역참조하여 할당한다. 또한 p의 메모리를 할당하는 과정에서 오류가 날 경우 프로그램을 종료하는 코드와 마지막에 p의 메모리를 해제해주는 코드를 추가하였다.
[1-2] 1개의 정수와 최대 크기가 20인 문자열로 이루어진 구조체를 저장할 수 있도록 동적 메모리를 할당 받고 여기에 정수 100과 문자열 ”just testing”을 저장한 다음, 동적 메모리를 반납하는 프로그램을 작성하라.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int a;
char c[20];
} sct;
int main(void) {
sct* s1;
s1 = (sct*)malloc(sizeof(sct));
if (s1 == NULL) {
fprintf(stderr, "동적메모리 할당 실패\n");
exit(1);
}
s1->a = 100;
strcpy_s(s1->c, 14, "just testing\0");
printf("s1의 a값 : %d\ns1의 c값 : %s", s1->a, s1->c);
free(s1);
return 0;
}
더보기
>> 구조체 포인터 s1에 동적 메모리를 할당하기 위해 먼저 sct구조체 사이즈 만큼의 공간을 설정하고 sct포인터로 형변환하여 공간을 만들어준다. s1에 메모리를 할당하는 과정에서 오류가 발생하면 프로그램을 종료시킨다.
s1이 가리키는 a의 값에는 100을 넣고 c에는 14길이 만큼의 문자열 “just testing\0”을 넣어 카피해주고 s1의 a와 c에 할당한 정수와 문자열이 정상적으로 들어갔는지 확인해보았다. 마지막에는 s1의 메모리를 해제하였다.
실행 결과
s1의 a값 : 100, s1의 c값 : just testing