malloc이 작동하는 방식
힙과 사용 가능한 목록을 배워 보세요.
malloc이 작동하는 방식은(는) CoddyKit의 무료 C Academy 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 C Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. C Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
malloc이 실제로 하는 일
malloc(n)을 호출하면 C 라이브러리는 최소 n개의 사용 가능한 바이트를 가리키는 포인터를 제공합니다. 하지만 힙은 할당자가 대신 관리하는 프로세스 메모리 영역일 뿐입니다.
할당자의 역할은 어떤 바이트가 사용 중인지, 어떤 바이트가 사용 가능한지 추적하고, 해제된 메모리를 효율적으로 재사용하도록 관리하는 것입니다.
힙은 OS에서 옵니다
할당자는 아무것도 없는 곳에서 메모리를 만들어 내지 않습니다. brk/sbrk나 mmap 같은 시스템 호출을 통해 OS에 큰 덩어리를 요청합니다.
그런 다음 이 덩어리를 더 작은 block으로 나누어 malloc 호출에 제공합니다. OS에 요청하는 일은 비용이 크므로 할당자는 메모리를 한꺼번에 요청하고 재활용합니다.
/* Conceptual: grow the heap by 4096 bytes */
void *base = sbrk(4096);
if (base == (void *)-1) {
/* out of memory */
}sbrk와 프로그램 브레이크
sbrk(n)는 "프로그램 브레이크"를 n바이트만큼 위로 이동하고 이전 브레이크를 반환합니다. 새로 노출된 영역은 사용할 수 있는 힙 공간이 됩니다.
이 방식은 선형적이고 단순하지만 중간에 있는 메모리를 쉽게 운영 체제에 반환할 수 없습니다. 최신 할당자는 큰 요청에 mmap을 사용하는 방식을 선호합니다.
void *prev_break = sbrk(0); /* current break */
sbrk(1024); /* grow by 1 KB */
/* prev_break now points to fresh memory */block 메타데이터
할당자는 각 할당에 대해 데이터 옆에 작은 헤더를 저장합니다. 헤더에는 크기와 사용 가능한 상태가 기록됩니다. 이 헤더 덕분에 free는 전달받은 데이터 포인터만으로도 작동할 수 있습니다.
malloc에서 받는 포인터는 헤더의 뒤를 가리키므로 메타데이터는 여러분에게 보이지 않습니다.
typedef struct block {
size_t size;
int free;
struct block *next;
} block_t;헤더 바로 다음의 포인터
일반적인 방법은 포인터 연산을 사용하는 것입니다. 사용자 포인터는 header + 1입니다. 사용자 포인터가 주어지면 헤더는 그보다 하나 앞에 있는 block_t입니다.
이 방식으로 free(p)는 여러분이 크기를 따로 전달하지 않아도 할당한 block의 크기를 알아냅니다.
block_t *hdr = (block_t *)user_ptr - 1;
printf("block size = %zu\n", hdr->size);작은 헤더 배치 예제
정적 버퍼 위에 헤더를 배치하고 다시 읽어 보겠습니다. 이를 통해 실제 할당자가 영역을 헤더와 페이로드로 나누는 방식을 확인할 수 있습니다.
OS 호출이 사용되지 않으므로 어디서나 실행할 수 있습니다.
#include <stdio.h>
#include <stddef.h>
typedef struct { size_t size; int free; } block_t;
static char buffer[256];
int main(void) {
block_t *h = (block_t *)buffer;
h->size = 64;
h->free = 0;
void *payload = (char *)buffer + sizeof(block_t);
printf("header bytes = %zu\n", sizeof(block_t));
printf("payload offset = %ld\n", (long)((char *)payload - buffer));
printf("size field = %zu\n", h->size);
return 0;
}free 목록의 개념
많은 할당자는 사용 가능한 block을 연결 리스트로 연결합니다. malloc을 호출하면 할당자는 이 리스트를 따라가며 충분히 큰 block을 찾습니다.
free를 호출하면 block을 사용 가능한 상태로 표시하고 나중에 재사용할 수 있도록 리스트에 돌려놓으므로, OS에 다시 요청할 필요가 없습니다.
block_t *find_free(block_t *head, size_t size) {
block_t *b = head;
while (b && !(b->free && b->size >= size))
b = b->next;
return b;
}free가 해야 하는 일
free(p)는 p의 헤더를 찾고 사용 가능한 상태로 표시한 다음, 인접한 사용 가능한 block과 병합하여 단편화를 줄이는 것이 이상적입니다.
같은 포인터를 두 번 free하거나 힙에 속하지 않는 포인터를 해제하면 정의되지 않은 동작이 발생합니다. 메타데이터가 손상되기 때문입니다.
void my_free(void *p) {
if (!p) return;
block_t *hdr = (block_t *)p - 1;
hdr->free = 1;
/* real allocators coalesce neighbors here */
}단편화
시간이 지나면서 서로 다른 크기를 할당하고 해제하면 빈틈이 생깁니다. 외부 단편화는 사용 가능한 메모리가 존재하지만 너무 작은 조각으로 흩어져 요청을 충족할 수 없는 상태를 뜻합니다.
내부 단편화는 필요한 크기보다 큰 block 내부에서 공간이 낭비되는 상태이며, 정렬이나 반올림 때문에 자주 발생합니다.
정렬 요구 사항
malloc은 모든 자료형에 맞게 정렬된 메모리를 반환해야 합니다. 대부분의 64비트 시스템에서는 이것이 16바이트 정렬을 의미하며 max_align_t를 충족합니다.
정렬되지 않은 포인터는 일부 CPU에서 충돌을 일으키거나 다른 CPU에서 접근을 느리게 할 수 있으므로, 할당자는 항상 페이로드 크기를 정렬 경계에 맞게 올림합니다.
#include <stdalign.h>
/* alignof(max_align_t) is the strictest required alignment */
size_t a = alignof(max_align_t);전체 구성하기
따라서 최소한의 할당자에는 메모리 원천(정적 버퍼, sbrk 또는 mmap), block별 헤더, 사용 가능한 공간을 찾는 전략, 정렬 처리가 필요합니다.
다음 레슨에서는 이 요소들을 구현합니다. 먼저 범프 할당자를 만들고, 그다음 사용 가능한 block 목록을 만들며, 마지막으로 정렬과 block 분할을 구현합니다.
/* The four pillars of a custom allocator */
/* 1. memory source 2. block headers */
/* 3. free-block search 4. alignment */빠른 확인
할당자 내부 구조에 대한 이해도를 확인해 보십시오.
복습
malloc은 sbrk 또는 mmap을 통해 OS에서 얻은 힙을 관리하고, 크기와 사용 가능 상태를 추적하는 숨겨진 헤더와 함께 이를 block으로 나눕니다.
사용 가능한 block 목록은 재사용을 가능하게 하고, 정렬은 모든 자료형에 맞는 메모리를 보장하며, 단편화는 핵심 과제입니다. 다음에 구현할 할당자는 이러한 개념을 바탕으로 합니다.
자주 묻는 질문
“malloc이 작동하는 방식” 강의는 무료인가요?
네 — “malloc이 작동하는 방식” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 C Academy 강의 전체를 잠금 해제할 수 있습니다. C Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“malloc이 작동하는 방식”에서 뭘 배우나요?
힙과 사용 가능한 목록을 배워 보세요. 브라우저에서 직접 실행하는 실습 코드로 C Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
C Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 C Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“malloc이 작동하는 방식” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 C Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 C Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- malloc이 작동하는 방식
- 간단한 범프 할당자
- 사용 가능 목록과 재사용
- 정렬과 분할