C - 동적 메모리 할당 ( Dynamic Memory Allocation )

   1. 프로세스의 메모리 구조

   2. malloc(), calloc(), realloc(), free()



1. 프로세스의 메모리 구조

프로그램이 실행되어 메모리에 올라가면 프로세스가될텐데, 이때 프로그램은 다음과 같은 구조로 메모리에 올라간다.


Text section

Text 영역 또는 Code 영역이라고하는 이 영역은 프로그램의 소스코드가 올라가는 영역이다. 이 영역은 'read only'인데 그 이유는 프로그램 코드 변조를 예방하기 위해서이다.


Data section

초기화된 전역변수나 static변수가 저장되는 영역이다.


BSS

초기화되지않은 전역변수나 static변수가 저장되는 영역이다. 물론 전역변수에 명시적으로 값을 대입시켜 초기화시켜주지 않아도 컴파일러가 자동으로 0으로 초기화해주지만 어쨋거나 대입연산자를 통해 명시적으로 초기화시켜준게 아니라면 BSS 영역에 저장된다.( 전역변수의 초기화여부에 따라 저장영역을 나눠논 이유는 잘모르겠다. )


Heap

동적으로 변수를 메모리에 할당할 때 이 영역에 저장된다.


Stack

지역변수나, 매개변수, 함수가 호출되고 리턴되고와 같은 행동이 이 영역에서 일어난다. 



2. malloc(), calloc(), realloc(), free()

malloc()함수의 반환타입은 void이기 때문에 잊지말고 타입캐스팅을 해야한다.

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

int main(int argc, char **argv) {
    int n, i, *ptr, sum=0;

    printf("Enter number of size: ");
    scanf("%d", &n);
    
    ptr = (int*)malloc(n * sizeof(int));
    if (ptr == NULL) {
        printf("Error: Memory not allocated");
        exit(0);
    }

    printf("Enter elements: ");
    for ( i=0; i<n; i++) {
        scanf("%d", ptr + i);
        sum += *(ptr + i);
    }

    printf("%d", sum);
    free(ptr);
    return 0;
}


calloc()함수는 malloc()함수와 같은데 추가적으로 할당받은 메모리 안의 값을 0으로 초기화한다.

calloc()함수의 내부구현을 보면 malloc()함수를 이용해 동적으로 메모리를 할당받고, 할당받은 주소값에 0으로 덮어씌운다.

다음 예제는 calloc()함수의 구현소스코드이다.

#include "ancidecl.h"
#include <stddef.h>

/* For systems with larger pointers than ints, this must be declared. */
PTR malloc (size_t);
void bzero (PTR, size_t);

PTR
calloc (size_t nelem, size_t elsize)
{
    register PTR ptr;

    if (nelem == 0 || elsize == 0)
        nelem = elsize = 1;

    ptr = malloc (nelem * elsize);
    if (ptr) bzero (ptr, nelem * elsize);

    return ptr;
}


realloc()함수는 malloc()함수를 통해 동적으로 할당받은 메모리의 공간의 크기를 다시 조정해주는 함수다.

Usage of realloc(): void* realloc(void *ptr, size_t size);

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

int main(int argc, char **argv) {
    int *buffer;

    /* get a initial memory block */
    buffer = (int*)malloc(10 * sizeof(int));
    if (buffer == NULL) {
        puts("Error: Failed allocate memory");
        exit(0);
    }

    /* get more memory with realloc */
    buffer = (int*)realloc(buffer, 20 * sizeof(int));
    if (buffer == NULL) {
        puts("Error: Failed allocate memory");
        exit(0);
    }

    free(buffer);
    return 0;
}