상세 컨텐츠

본문 제목

[C] malloc, calloc, realloc을 이용한 메모리 동적 할당

Programming/C언어

by 영상털이범 2014. 6. 26. 00:31

본문

동적할당을 사용하는 이유는 무엇일까?

c언어의 메모리 구조에 대해서 알고 있다면 동적할당을 사용하는 이유를 쉽게 알 것이다.


2014/06/26 - [Programming/C언어] - [C] 스택(Stack), 힙(Heap), 데이터(Data)영역



malloc 함수

 - 동적으로 메모리를 할당하는 함수 (힙 영역에 메모리를 할당)


#include <stdlib.h>

void* malloc(size_t size)	// malloc 함수의 원형

함수 호출시 할당하고자 하는 메모리의 크기를 바이트 단위로 전달하면 그 크기만큼 메모리를 할당하게 된다.

그리고 할당한 메모리의 주소(첫 번째 바이트의 주소)를 리턴한다.

메모리 할당에 실패하면 NULL이 리턴된다.


리턴형이 void*(void 포인터) ??


malloc은 단순히 메모리만 할당하는 함수이기 때문에 개발자가 어떠한 데이터 형을 저장하는지 예측할 수 없다.

예를들어 4바이트를 할당하였을 경우 int형 데이터를 저장하기 위해서 사용하는지, float형 데이터를 사용하는지 예측할 수 없기 때문에 void포인터를 반환하여 개발자가 알맞은 용도로 변환하여 사용할 수 있도록 만든것이다.


예를들어 int형 데이터를 저장하기 위해서는 리턴되는 void*을 int*로 변환해야 한다.

int *i = (int*) malloc (sizeof(int));



위의 그림은 포인터 변수 i에 4바이트를 할당하는 그림이다.


1. sizeof(int)의 값은 4이다. 4라는 값을 전달하면서 malloc 함수를 호출한다.

2. 할당된 메모리의 주소가 void*형으로 리턴된다. 리턴되는 void*를 사용하려는 int*형으로 변환한다.

3. 포인터 변수 i에 대입한다.


malloc함수 사용 예

동적 할당을 사용하여 arr_1의 배열의 값을 대입하는 소스를 보며 malloc함수 사용법을 이해해보자.

#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;
}



free 함수

 - 힙 영역에 할당된 메모리를 해제하는 함수


메모리를 할당만 하고 해제해 주지 않는다면, 언젠가는 메모리가 부족한 현상이 발생 할 것이다.

할당된 메모리가 더 이상 필요하지 않을경우 free함수를 이용하여 메모리를 해제시켜 줘야한다.


#include <stdlib.h>

void free(void* ptr)	// free 함수의 원형


free함수 사용 예

위의 예제에서 free함수만 추가시켰다.

#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;
}



calloc 함수

 - calloc함수는 malloc함수와 같은 기능을 지니고 있다. 다만 사용하는 형태가 조금 다를 뿐이다.


#include <stdlib.h>

void* calloc(size_t elt_count, size_t elt_size)	// calloc 함수 원형

calloc 함수는 elt_size 크기의 변수를 elt_count 개 만큼 저장할 수 있는 메모리 공간을 할당하라는 의미를 갖는다.


calloc함수 사용 예

위의 예제에서 malloc 함수대신 calloc 함수를 사용하였다.

#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;
}

malloc함수와 calloc함수의 차이점!

malloc은 할당된 공간의 값을은 바꾸지 않는다.

calloc은 할당된 공간의 값을 모두 0으로 바꾼다.

배열을 할당하고 모두 0으로 초기화할 필요가 있을경우에는 calloc을 쓰면 편하다.




realloc 함수

 - 이미 할당한 공간의 크기를 바꿀 때 realloc 함수를 사용한다.


#include <stdlib.h>

void* realloc(void* memblock, size_t size);	// realloc 함수의 원형

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


realloc함수 사용 예

malloc함수를 사용한 예제에서 realloc 함수를 사용하여 변경하였다.


#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;
}



관련글 더보기

댓글 영역

  • 프로필 사진
    2015.03.05 22:35
    잘보고갑니다
  • 프로필 사진
    2015.09.29 16:32
    정리를 정말 깔끔하게 해두셨네요. 잘 보고 갑니다.
  • 프로필 사진
    2015.10.03 11:44
    디테일한 부분까지~~ 엔지니어의 숨결이..
  • 프로필 사진
    2015.12.23 00:04
    안녕하세요, C언어를 공부하고 있는 고등학생입니다.

    malloc을 통한 동적할당을 쓰고 싶은 곳이 있어 공부하고 있는 중인데,
    자꾸 return이 실행되기 직전에 프로그램이 중지되네요...;;

    짠 코드는,

    int *seque, size;
    scanf("%d", &size);

    seque = (int *)malloc(size);
    int i;
    for(i=0; i<size; i++){
    seque[i]=i;
    }
    for(i=0; i<size; i++){
    printf("%d ", seque[i]);
    }
    printf("\n");
    printf("TheEnd_________________EndLine_________________\n");
    free(seque);

    return 0;
    }

    입니다. 16, 32와 같은 수를 입력해주면 분명히 그 전 수 까지 다 출력하고

    TheEnd_________________EndLine_________________ 도 문제 없이 출력합니다.
    그런데, 그 직후에 프로그램 실행 성공에 대한 정보(IDE는 Dev Cpp를 사용하고 있습니다.)를 띄우지 못하고 중지되었다는 알림이 뜹니다.

    같은 코드를 int형으로 하지 않고, char 형으로 바꾸어 하면 문제가 없이 실행 종료까지 되고요.

    뭐가 문제이고 어떻게 해야하나요?

    • 프로필 사진
      2016.01.11 16:51
      size가 integer형이기 때문에 크기는 4byte입니다.
      동적할당을 seque에 하고 싶다면 seque = (int *)malloc(sizeof(int)*size)라고 하는게 맞는 것 같습니다.
  • 프로필 사진
    2016.01.19 17:31
    그렇군요... calloc( )의 예가 잘 정리되있네여 감사감사
  • 프로필 사진
    2016.01.26 01:20
    비밀댓글입니다
  • 프로필 사진
    2016.05.04 13:09
    Good!! 정리 잘되있네요
  • 프로필 사진
    2016.05.08 18:15
    너무 좋은 글 감사합니다!
  • 프로필 사진
    2016.06.15 09:04
    동적할당 ㅎㅎ
    잘보고갑니다
  • 프로필 사진
    2016.07.05 17:56

    리버싱 공부하면서 책이나 인터넷에 그렇다고 하니 그런줄말알고 넘어갔던 내용들인데
    정리가 잘 되어있어 공부하는데 많은 도움이 되었습니다. 감사합니다
  • 프로필 사진
    2016.10.12 21:02
    대학교 컴공 3학년인데 먼말인지 모르겠네요 ㅎ

    자살각
  • 프로필 사진
    2016.11.24 11:14
    깔끔한 설명 감사합니다
  • 프로필 사진
    2017.09.05 22:56
    감사합니다 덕분에 잘배워갑니다!
  • 프로필 사진
    2018.06.09 22:37
    와우, 깔끔한 설명 감사합니다.
  • 프로필 사진
    2019.06.02 19:49
    윤성우 책 보다가 봤는데 이해가 너무 잘 되네요 감사합니다 !!
  • 프로필 사진
    2019.06.02 19:49
    윤성우 책 보다가 봤는데 이해가 너무 잘 되네요 감사합니다 !!
  • 프로필 사진
    2019.07.30 17:31
    동적할당 함수에 대해 궁금하여 찾아보다가 잘 보고 갑니다. 확실히 같은 프로그램 안에서 다른 사용 예시를 보여주니 이해가 빠르네요. 감사합니다.