본문 바로가기
C C++/C언어 기초

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

by Go! Jake 2022. 7. 9.

앞 서 알아 본 메모리 구조에서 사용자가 원하는 시점에 할당하고 소멸시킬 수 있는 메모리는 힙 영역에 할당이 된다고 언급하였습니다. 그렇다면 사용자가 원하시는 시점에 할당과 소멸을 어떻게 할 수 있을까요? 통상 C에서는 malloc, calloc, realloc 함수로 할당하며, C++에서도 사용 가능합니다.

동적 메모리 할당 (malloc 예시)

동적 메모리 할당은 힙에 메모리를 할당하며, 유저가 원하는 시점에 생성과 소멸 시킬 수 있습니다.

mlloc 함수와 free함수를 통해 생성과 소멸이 가능합니다.

 

동적 메모리 할당의 가장 큰 목적은 메모리 공간을 지정한대로 사용할 수 있다는 점입니다. 아래 문제점을 먼저 보겠습니다.

#include <iostream>
#include <stdlib.h>

int* num()
{
	int num_value;
	num_value=10;
	return &num_value;
}

int main() 
{
	int* val;
	val=num();
	printf("%d", *val);
	return 0;
}

위 코드는 main 함수에서 int* num() 함수로부터 num_value의 주소값을 리턴받고 있습니다.

Dev C++에서는 경고창이 발생합니다.

[Warning] address of local variable 'num_value' returned [-Wreturn-local-addr]

 

이는 int* num() 함수의 로컬 변수인 num_value의 주소는 함수 호출이 끝나고 언제든 소멸될 수 있기 때문입니다. 이 경우 주소값이 보전되지 않아 문제가 생길 수 있습니다. 따라서 우리는 이 때 malloc 함수를 통해 할당한 메모리를 사용할 수 있습니다.

#include <iostream>
#include <stdlib.h>

int* num()
{
	int* num_value = (int*) malloc(sizeof(int)*1);
	*num_value=10;
	return num_value;
}

int main() 
{
	int* val;
	val=num();
	printf("%d", *val);
	free(val);
	return 0;
}

int* num() 함수 내에 int* num_value 포인터에 대해 malloc으로 메모리를 할당하였습니다. 이제 저 메모리는 int* num_value를 위한 메모리가 된다. free(val) 이전까지 계속해서 메모리에 존재하게 됩니다.

 

이 경우 할당된 메모리에 값을 유지하고 있기 때문에, 앞 선 지역 변수와 상관 없이 경고창이 발생하지 않습니다.

구체적인 할당 방법 (malloc, calloc, realloc)

malloc 함수

void* malloc(size_t size)

void* free(void* ptr)

malloc함수의 기본 반환형은 void*입니다. 어떤 데이터 타입이 할당될 지 모르기 때문입니다. 포인터 형 변환해서 직접 설정해야 합니다.아래와 같이 선언 해 주면됩니다. malloc 앞에 (type*)을 붙입니다. 괄호 안에는 할당할 바이트 크기가 입력됩니다.

int* ptr1 = (int*)malloc(sizeof(int));
double* ptr2 = (double*)malloc(sizeof(double));
free(ptr1);
free(ptr2);

calloc 함수

void* calloc(size_t elt_count, size_t elt_size);

void* free(void* ptr)

calloc 함수 안에는 첫 번째 인자로 할당할 블록 (e.g. 4바이트), 두 번째 인자로 블록 개수가 입력됩니다. 둘을 곱하여 총 바이트 숫자가 됩니다.

 

recalloc 함수

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

void* free(void* ptr)

realloc은 할당된 크기를 확장할 때 사용됩니다. 첫 번째 인자로 확장할 포인터, 두 번째 인자로 확장하고자 하는 메모리 전체 크기를 전달합니다. (기존 112였는 데, 120을 입력하면 120으로 확장 됨.)

댓글