Adventure Time - Finn 3

새소식

C언어

[C] 동적 메모리 할당(malloc, calloc, realloc)

  • -

1.동적 메모리 할당이란?

- 프로세스는 더 큰 메모리를 할당해서 사용할 수 있도록 힙(Heap)영역을 제공한다.

- 힙영역은 지역변수와 매개변수등을 저장하는 스택(Stack)영역과 달리 실행시점에 원하는 크기만큼 메모리를 할당할 수 있습니다.

- 메모리 사용이 끝나면 언제든지 할당한 메모리 공간을 해제할 수 있습니다.

 

 

1.1 malloc

- 힙은 스택처럼 관리되는 공간이 아니라서 변수를 선언하는 행위로 메모리를 할당할 수 없습니다. 그렇기 때문에 C 표준 함수인 malloc과

free를 통해서 메모리 할당 및 해제 해야합니다.

 

 

- 함수 원형

void *malloc(size_t size); /* size_t는 unsigned int와 같음 */

 

- void*를 사용하면 형 변환을 해야하는 불편함이 있기 때문에 주소를 받는 시점에 사용할 포인터에 미리 형 변환을 사용하는 것이 좋다.

 

 

- 예시 코드(int로 형 변환해서 받음)

#include <stdio.h>
#include <stdlib.h>

int main() {
	int arr_1[5];	// 배열 선언
	int *arr_2;		// 포인터 변수 선언
	int i;

	for(i = 0; i < 5; i++) {
		arr_1[i] = i+1;	// 배열에 값 대입
	}

	arr_2 = (int*) malloc(sizeof(int)*5);	// 메모리 할당, 배열의 크기만큼 할당하기 위해 5를 곱함

	for(i = 0; i < 5; i++) {
		arr_2[i] = arr_1[i];
		printf("%d ", arr_2[i]);
	}

	return 0;
}

 

 

 

1.2 free 

 

- free 함수는 힙 영역에 할당된 메모리를 해제하는 함수입니다.

- free 함수를 사용하지 않으면 메모리를 낭비하게 되고 언젠가는 메모리가 부족한 현상이 발생할 것 입니다.

 

 

- 함수 원형

void free(void* ptr);

 

- 예시 코드

#include <stdio.h>
#include <stdlib.h>

int main() {
	int arr_1[5];	// 배열 선언
	int *arr_2;		// 포인터 변수 선언
	int i;

	for(i = 0; i < 5; i++) {
		arr_1[i] = i+1;	// 배열에 값 대입
	}

	arr_2 = (int*) malloc(sizeof(int)*5);	// 메모리 할당, 배열의 크기만큼 할당하기 위해 5를 곱함

	for(i = 0; i < 5; i++) {
		arr_2[i] = arr_1[i];
		printf("%d ", arr_2[i]);
	}

	free(arr_2);	// free함수를 이용하여 메모리 해제

	return 0;
}

 

 

1.3 calloc

 

- calloc은 malloc과 힙 영역에 할당하는 것은 똑같습니다. 하지만 calloc은 할당된 메모리를 전부 0으로 초기화 시켜줍니다.

 

- 함수 원형

void *calloc(size_t n, size_t size);

 

- 위의 코드는 size 크기의 변수를 n 개 만큼 저장할 수 있는 메모리 공간을 할당하라는 의미를 갖습니다.

 

 

- 예시 코드 

#include <stdio.h>
#include <stdlib.h>

int main() {
	int arr_1[5];	// 배열 선언
	int *arr_2;		// 포인터 변수 선언
	int i;

	for(i = 0; i < 5; i++) {
		arr_1[i] = i+1;	// 배열에 값 대입
	}

	//arr_2 = (int*) malloc(sizeof(int)*5);	// 메모리 할당, 배열의 크기만큼 할당하기 위해 5를 곱함
	arr_2 = (int*) calloc(5, sizeof(int));	// sizoe(int)크기의 변수를 5개 저장할 수 있는 공간할당

	for(i = 0; i < 5; i++) {
		arr_2[i] = arr_1[i];
		printf("%d ", arr_2[i]);
	}

	free(arr_2);	// free함수를 이용하여 메모리 해제

	return 0;
}

 

 

1.4 realloc

- 이미 할당된 공간의 크기를 줄이거나 늘릴 때 realloc 함수를 사용합니다.

 

- 함수 원형

void* realloc(void* memblock, size_t size);

 

- 이미 할당한 포인터 변수를 memblock에 넣고, 바꾸고 싶은 공간의 크기를 size에 입력해서 사용합니다.

 

- 예시 코드

#include <stdio.h>
#include <stdlib.h>

int main() {
	int arr_1[10];	// 배열 선언
	int *arr_2;		// 포인터 변수 선언
	int i;

	for(i = 0; i < 10; i++) {
		arr_1[i] = i+1;	// 배열에 값 대입
	}

	arr_2 = (int*) malloc(sizeof(int)*5);	// 메모리 할당, 배열의 크기만큼 할당하기 위해 5를 곱함

	for(i = 0; i < 5; i++) {
		arr_2[i] = arr_1[i];
		printf("%d ", arr_2[i]);
	}

	printf("\n");

	// sizeof(int) = 4바이트
	realloc(arr_2, sizeof(int)*10);	// arr_2의 메모리를 40바이트로 재 할당
	// arr_2의 메모리 크기 : 20바이트 -> 40바이트

	for(i = 0; i < 10; i++) {
		arr_2[i] = arr_1[i];
		printf("%d ", arr_2[i]);
	}

	free(arr_2);	// free함수를 이용하여 메모리 해제

	return 0;
}

 

 

 

2. 동적 메모리 할당의 장단점

장점

- 힙에 동적으로 사용하는 메모리는 스택에 비해 큰 크기의 메모리를 할당할 수 있으며, 할당하고 해제하는 시점도 프로그래머가 직접 정할 수 있다.

 

- 동적 메모리 할당은 실행 중에 필요한 메모리를 할당하므로, 메모리 요구 사항이 실행 시간에 동적으로 변경될 수 있습니다. 이는 프로그램이 더 효율적으로 메모리를 사용하고, 유연하게 대처할 수 있도록 해줍니다.

 

- 정적 메모리 할당 방식에서는 프로그램이 필요로 하는 최대 메모리 양을 미리 예상하여 할당해야 합니다. 하지만 동적 메모리 할당은 필요한 만큼의 메모리만 할당하므로, 메모리 사용량을 최적화하여 효율적인 메모리 관리가 가능합니다.

 

단점

- 동적 메모리 할당을 사용할 때, 메모리를 할당한 후에는 반드시 해당 메모리를 해제해야 합니다. 그렇지 않으면 메모리 누수가 발생하여 할당된 메모리를 더 이상 사용할 수 없게 됩니다.

 

- 동적 메모리 할당을 반복적으로 수행하면, 메모리가 작은 조각들로 나뉘어지는 메모리 단편화가 발생할 수 있습니다.

 

 

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.