메모리를 동적으로 할당 받는 이유는 일반 변수는 컴파일 단계에서 변수의 크기가 정해지기 때문에 프로그램이 실행 되면서 얼마만큼의 배열크기를 사용하게 될지 정확히 알 수 없기 때문에 넉넉하게 할당 받는다. 그래서 프로그램이 실행도중에 사용자가 원하는 만큼 메모리를 할당 받을 수 있다면 메모리 낭비가 줄어들고 프로그램도 안정적으로 동작이 된다. 그래서 나온 개념이 메모리 동적 할당이다.

C언어에는 Heap 영역에 사용자가 원하는 크기만큼 메모리를 할당받아 사용할 수 있다.


그것을 지원하는 3가지 함수가 있는데 malloc, calloc, realloc 이다. 이 포스팅에서는 이 3가지 함수에 차이점에 대해서 배워보도록 하자. 기본적으로 malloc 을 많이 사용하지만 다른 함수들도 알아 두면 유용할때가 많다.


그리고 참고로 메모리를 해제하는 함수는 free이다. 메모리를 할당하고 해제하지 않으면 나중에 사용할 heap 영역에 크기가 부족해 프로그램이 정상동작하지 않을 수 있다.


우선 malloc과 free에 기본적인 사용방법은 아래 링크를 참고하자. 정확히 이해하지 않으면 이번 포스팅이 어려울 수 있다.


C/C++ malloc, free를 사용한 메모리 할당 및 해제 : http://hijuworld.tistory.com/59


그리고 메모리 할당과 해제를 하는 원리는 아래 링크를 참고하자.


C, C++ 에서 동적 메모리의 할당과 해제 원리 : http://hijuworld.tistory.com/28





malloc과 calloc의 차이에 대해서 알아보자.


1. 할당받을 메모리 사이즈를 받는 파라미터의 갯수가 다르다.

2. calloc은 메모리 할당을 받고 0으로 초기화 한다.



우선 함수의 선언을 보면 아래와 같다.


void *malloc(size_t size);

void *calloc(size_t num, size_t size);


malloc은 메모리를 할당받을 사이즈 하나만을 파라미터로 받는 반면

calloc은 메모리를 할당받을 사이즈에 그 메모리를 몇개를 할당 받을지 갯수도 파라미터로 받는다.

둘다 void 포인터를 반환하는데 그 이유는 할당한 메모리를 어떤 크기로 잘라서 사용할지는 그때그때 다르기 때문에 사용자가 강제형변환을 통해 사용하면 되기 때문이다. 


아래 간단한 예제를 보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <stdlib.h>
 
int main() {        
    int *pi1; 
    int *pi2;
 
    pi1 = (int *)malloc(sizeof(int* 3); //할당
    pi1[0= 1;
    pi1[1= 5;
    pi1[2= 8;
    
    pi2 = (int *)calloc(3sizeof(int)); //할당
    pi2[0= 1;
    pi2[1= 5;
    pi2[2= 8;    
 
    free(pi1); //메모리 해제
    free(pi2); //메모리 해제
}
cs


pi1 은 malloc으로 할당을 받고 pi2 는 calloc으로 할당을 받았다. 

파라미터의 갯수 말고도 더 큰 차이가 있다.

바로 calloc은 메모리를 할당과 동시에 0으로 초기화 하는 것이다.


아래 예제를 보자. 모두 할당만 하고 값을 출력시켜 보았다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <stdlib.h>
 
int main() {        
    int *pi1; 
    int *pi2;
 
    pi1 = (int *)malloc(sizeof(int* 3); //할당
    printf("malloc : %d %d %d\n", pi1[0], pi1[1], pi1[2]);
    
    pi2 = (int *)calloc(3sizeof(int)); //할당
    printf("calloc : %d %d %d\n", pi2[0], pi2[1], pi2[2]);
 
    free(pi1); //메모리 해제
    free(pi2); //메모리 해제
}
cs



출력결과

malloc : -842150451 -842150451 -842150451

calloc : 0 0 0                                          


할당하면서 0으로 초기화가 되기때문에 상황에 따라 편리할 수 있다.


realloc에대해서 알아보자.

realloc은 malloc이나 calloc으로 할당받은 메모리의 사이즈를 변경할 때 사용한다.


함수선언은 아래와 같다.

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


파라미터로 기존에 할당받았던 메모리를 전달하고 다음 파라미터로 새로 할당 받을 size를 전달한다.


아래 예제를 보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h>
 
int main() 
{        
    int i;
    int *pi = (int *)malloc(sizeof(int* 3); //4x3 메모리 할당
    for (i = 0; i < 3; i++)
        pi[i] = i * 4;
    for (i = 0; i < 3; i++)
        printf("pi[%d] : memory %d %d\n", i, &pi[i], pi[i]);
    printf("-----------------------------\n");
 
    pi = (int *)realloc(pi,sizeof(int* 5); //4x5 메모리 재할당
    for (i = 3; i < 5; i++)
        pi[i] = i * 4;
    for (i = 0; i < 5; i++)
        printf("pi[%d] : memory %d %d\n", i, &pi[i], pi[i]);
    printf("-----------------------------\n");
 
    free(pi); //메모리 해제
}
cs


출력결과

pi[0] : memory 9457232 0  

pi[1] : memory 9457236 4  

pi[2] : memory 9457240 8  

-----------------------------  

pi[0] : memory 9457232 0  

pi[1] : memory 9457236 4  

pi[2] : memory 9457240 8  

pi[3] : memory 9457244 12 

pi[4] : memory 9457248 16 

-----------------------------  


처음 4X3 메모리를 할당받았고 그다음에는 4X5 메모리를 재할당 받았다.

재할당 받은 뒤에 기존에 할당받았던 값 이외에 값인 4번째, 5번째에만 값을 넣어준다.

재할당 받은 뒤에도 기존에 값은 정상적으로 존재하는 것을 확인할 수 있다.

단순히 메모리 사이즈만 변경하는 것이 아닌 내용물도 복사를 한다.

 

그리고 메모리의 주소값이 같은것을 볼 수 있는데 이것은 보장하지는 않는다.

완전 새로운 메모리에 값을 새로 할당받아 값을 복사할 수도 있다.


아래 예제를 보자. 메모리를 기존보다 훨씬 크게 할당한 것을 볼 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h>
 
int main() 
{        
    int i;
    int *pi = (int *)malloc(sizeof(int* 30000); // 메모리 할당
    for (i = 0; i < 3; i++)
        pi[i] = i * 4;
    for (i = 0; i < 3; i++)
        printf("pi[%d] : memory %d %d\n",i,&pi[i],pi[i]);
    printf("-----------------------------\n");
 
    pi = (int *)realloc(pi,sizeof(int* 5000000); // 메모리 재할당
    for (i = 3; i < 5; i++)
        pi[i] = i * 4;
    for (i = 0; i < 5; i++)
        printf("pi[%d] : memory %d %d\n", i, &pi[i], pi[i]);
    printf("-----------------------------\n");
 
    free(pi); //메모리 해제
}
cs

출력결과

pi[0] : memory 17674192 0 

pi[1] : memory 17674196 4 

pi[2] : memory 17674200 8 

-----------------------------  

pi[0] : memory 21880896 0 

pi[1] : memory 21880900 4 

pi[2] : memory 21880904 8 

pi[3] : memory 21880908 12

pi[4] : memory 21880912 16

----------------------------- 


메모리의 주소값이 달라진 것을 볼 수 있다. 하지만 0, 4, 8은 잘 복사된 것을 볼 수 있다.




Posted by 꿈만은공돌
,