지난 포스팅에서 메모리 동적 할당에 대해 설명하고 있습니다.
realloc과 calloc은 그의 연장선입니다. 아래 포스팅을 참고해주세요.
[C/C++] 메모리 동적할당 및 해제 (malloc, free) 사용법 (tistory.com)
calloc
우선 calloc()의 함수 원형은 아래와 같습니다.
#include <stdlib.h>
void *calloc(size_t number, size_t size);
number : 할당받을 메모리 요소의 개수를 말합니다.
size : 각 요소의 크기를 말합니다. (자료형의 크기, byte 단위)
calloc()는 malloc()와 마찬가지로 원하는 크기의 메모리를 동적으로 할당받는 역할을 합니다.
하지만 차이점이 있습니다.
- 할당받을 byte의 크기만큼 한 번에 받는 게 아닌 요소(자료형)의 크기(byte)와 개수로 나누어 매개변수를 받습니다.
- 메모리 할당과 동시에 값을 0으로 초기화합니다.
위 두 가지의 차이를 빼면 malloc과 동일하다고 생각하시면 됩니다.
예제)
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int *pMint;
int *pCint;
int count = 5;
pMint = (int *)malloc(sizeof(int) * count);
pCint = (int *)calloc(count, sizeof(int));
for(int i=0; i<count; i++)
{
printf("pMint[%d] = %d / pCint[%d] = %d\n", i, pMint[i], i, pCint[i]);
}
free(pMint);
free(pCint);
return 0;
}
pMint[0] = -1163005939 / pCint[0] = 0
pMint[1] = -1163005939 / pCint[1] = 0
pMint[2] = -1163005939 / pCint[2] = 0
pMint[3] = -1163005939 / pCint[3] = 0
pMint[4] = -1163005939 / pCint[4] = 0
위 예제에서 볼 수 있는 것처럼 malloc()은 요소의 크기와 개수의 곱으로, calloc()은 요소의 크기와 개수를 별도로 입력하고 있습니다.
또한 차이점 두 번째인 calloc()은 메모리를 0으로 초기화한다는 것도 결과 로그를 통해 알 수 있습니다. malloc()은 garbage data가 들어있음을 확인할 수 있습니다.
realloc
realloc의 함수 원형은 아래와 같습니다.
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
*ptr : 이미 동적 할당을 받은 메모리의 주소(ptr)를 말합니다.
size : 새로 할당받을 크기를 입력합니다.
realloc()은 함수의 이름에서 보이듯 할당받은 메모리를 원하는 사이즈로 다시(re) 할당받는 기능을 합니다.
여기서 size는 malloc()를 사용할 때처럼 할당받을 메모리의 크기 전체를 입력하면 됩니다.
예제)
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
int main(void)
{
int* pMint;
int* pRint;
int mallocSize, reallocSize;
int count = 5;
pMint = (int*)malloc(sizeof(int) * count);
mallocSize = _msize(pMint);
pRint = (int*)realloc(pMint, (count + 2) * sizeof(int));
reallocSize = _msize(pRint);
printf("malloc size : %d / realloc size : %d\n", mallocSize, reallocSize);
if((pMint != NULL) && (pRint != NULL))
{
printf("malloc : 0x%p / realloc : 0x%p\n", pMint, pRint);
for (int i = 0; i < count + 2; i++)
{
printf("pRint[%d] = %d\n", i, pRint[i]);
}
}
free(pRint);
return 0;
}
malloc size : 20 / realloc size : 28
malloc : 0x00B12838 / realloc : 0x00B12838
pRint[0] = 11610576
pRint[1] = 11600064
pRint[2] = 754974765
pRint[3] = 875
pRint[4] = 11610576
pRint[5] = 11600064
pRint[6] = 721420331
출력 결과를 봤을 때 몇 가지 짚고 넘어가야 할 게 있습니다.
1. realloc를 통해 다시 할당받은 메모리는 주소 값이 이전과 같을 수도 다를 수도 있습니다.
그렇기 때문에 이전에 사용하던 주소와 값은 무의미해집니다.
2. malloc과 마찬가지로 값을 초기화하지 않고 할당합니다.
3. 예제에서는 크기를 더 키웠지만 반대로 줄이는 것도 가능합니다.
참고)
참고로 위에서 사용된 _msize()라는 함수는 할당받은 메모리의 크기를 확인할 수 있습니다.
<malloc.h>를 추가해 사용이 가능합니다.
예제는 malloc()과 realloc()의 차이를 설명하기 위해서 변수를 다르게 사용했지만 사실 아래와 같은 형태로 많이 사용합니다.
pMint = (int*)realloc(pMint, (count + 2) * sizeof(int));
이처럼 사용하던 포인터 변수에 다시 할당을 받는 것인데요. 이는 단순히 스타일이긴 하지만 무의미하게 변수를 많이 만들어 쓰지 않기 때문에 가독성 및 운용 방법면에서 좋습니다.
하지만 이처럼 쓸 때는 조심해야 할 게 있습니다. 만약 realloc 하지 못해 에러 값, 즉 'NULL'을 반환받게 된다면 이전에 할당받은 메모리의 주소를 잃기 때문에 free 하지 못해 '메모리 누수'가 발생할 수 있기 때문입니다.
참고) 메모리 누수란?
메모리 누수는 영어로 menory leak이라고 하는데, 프로그램 동작중에 더 이상 사용되지 않는(필요 없는) 메모리가 계속 점유하고 있는 현상으로 메모리 누수가 증가하면 메모리가 낭비되는 영역이 늘어나고 사용 가능한 메모리 공간이 그만큼 없어진다는 의미가 됩니다.
'[R&D] 프로그래밍 > C, C++' 카테고리의 다른 글
[C/C++] 메모리 동적할당 및 해제 (malloc, free) 사용법 (0) | 2022.08.01 |
---|---|
[C/C++] 배열이란? - 배열의 개념 및 기본 사용법 (2) | 2022.07.28 |
[C/C++] 포인터(pointer)란? - 포인터의 기본 개념 (2) | 2022.07.27 |
[C++] 자료형 확인 방법 (type_info name) (0) | 2022.07.19 |
[C/C++] 자료형 크기 및 범위 정리 (0) | 2022.07.13 |
댓글