일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- 백준 1707번
- 이분 탐색(Binary Search)
- 위상 정렬(Topological Sort)
- DFS(Depth First Search)
- 위상 정렬(Topology Sort)
- 스택(Stack)
- BFS(Breadth First Search)
- 백준 21606번
- 그리디 알고리즘(Greedy Algorithm)
- 백준 2812번
- 다익스트라 알고리즘(Dijkstra Algorithm)
- 분할 정복(Divide and Conquer)
- 알고리즘 개념
- 큐(Queue)
- 백준 18352번
- BFS
- 백준 1948번
- 그래프(Graph)
- 백준 10000번
- 백준 17608번
- 이분 그래프(Bipartite Graph)
- DFS
- 백준 9012번
- 트리(Tree)
- DFS & BFS
- 백준 2261번
- 백준 2504번
- 백준 2493번
- 플로이드 워셜 알고리즘(Floyd-Warshall Algorithm)
- 동적 프로그래밍(Dynamic Programming)
- Today
- Total
Always Be Wise
동적 메모리 할당 - malloc 함수 구현(묵시적 가용 리스트 이용) 본문
묵시적 가용 리스트
실용적인 할당기는 블록 경계를 구분하고, 할당된 블록과 가용 블록을 구분하는 데이터 구조를 필요로 한다. 대부분의 할당기는
이 정보를 블록 내에 저장한다. 아래는 블록의 구성 예시로, 한 블록은 1워드(4바이트)의 헤더와 데이터, 추가적인 패딩으로
이루어진다. 헤더는 블록 크기(헤더와 추가적인 패딩을 포함한)와 블록의 할당 여부를 인코딩한다. 헤더 다음에는 데이터가
따라온다. 데이터 다음에는 패딩이 따라올 수 있는데 이들의 크기는 가변적이다. 패딩을 해야 하는 데는 여러 가지 이유가 있다.
예를 들어, 외부 단편화를 극복하기 위한 전략이거나 정렬 요구 사항을 만족하기 위해 필요할 수 있다.

위와 같은 블록이 주어졌을 때, 힙을 연속된 할당 및 가용 블록의 배열로 아래와 같이 구성할 수 있다.
이러한 구조를 묵시적 가용 리스트라고 부르는데, 이는 가용 블록이 헤더 내 필드에 의해 묵시적으로 연결되기 때문이다.
마지막 블록의 헤더는 종료를 나타내기 위해서 할당 비트가 1로 지정되어 있고 크기는 0을 갖는다.

프로그래미 특정 크기의 블록을 요청할 때, 할당기는 요청한 블록을 저장하기에 충분히 큰 가용 블록을 리스트에서 검색한다.
검색을 수행하는 방법에는 First Fit, Next Git, Best Fit이 주로 사용된다.
- First Fit : 가용 리스트를 처음부터 검색해서 크기가 맞는 첫 번째 가용 블록을 선택한다.
- Next Fit : 이전 검색이 종료된 지점에서 검색을 시작한다.
- Best Fit : 모든 가용 블록을 검사하며 크기가 맞는 가장 작은 블록을 선택한다.
할당기가 크기가 맞는 가용 블록을 찾은 후에 가용 블록을 어느 정도를 할당할지에 대해 결정을 내려야 한다. 한 가지 옵션은 해당
가용 블록 전체를 사용하는 것이다. 간단하고 빠르지만 내부 단편화가 생길 수 있다는 단점이 있다. 따라서 할당기는 가용 블록을
두 부분으로 나누어 사용한다. 만약 할당기가 요청한 블록을 찾을 수 없다면 물리적으로 인접한 가용 블록들을 연결해서 더 큰
가용 블록을 만들거나 가용 블록이 이미 최대로 연결되었다면 커널에 함수를 호출하여 추가적인 힙 메모리를 요청한다.
할당기가 할당한 블록을 반환할 때, 아래 그림과 같이 새롭게 반환하는 블록에 인접한 다른 가용 블록들이 있을 수 있다.

이 경우 위의 그림과 같이 가용 가능한 블록(16/0)이 두 개로 나뉘어져 있다. 이를 오류 단편화(False Fragmentation)라고 한다.
이를 극복하기 위해 연결(Coalescing)이라는 과정을 이용하여 인접 가용 블록들을 통합한다. 할당기가 연결을 효율적으로
구현하는 방법은 경계 태그, 풋터(Footer)를 이용한 방식이다. 풋터는 헤더를 복사한 것으로 헤더와 마찬가지로 4바이트를
차지한다. 각 블록에 풋터를 포함시켜 할당기는 시작 위치와 이전 블록의 상태를 자신의 풋터를 조사해서 결정할 수 있게 된다.
▶ 구현 코드(First Fit)
/*
* mm-naive.c - The fastest, least memory-efficient malloc package.
*
* In this naive approach, a block is allocated by simply incrementing
* the brk pointer. A block is pure payload. There are no headers or
* footers. Blocks are never coalesced or reused. Realloc is
* implemented directly using mm_malloc and mm_free.
*
* NOTE TO STUDENTS: Replace this header comment with your own header
* comment that gives a high level description of your solution.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include "mm.h"
#include "memlib.h"
/*********************************************************
* NOTE TO STUDENTS: Before you do anything else, please
* provide your team information in the following struct.
********************************************************/
/* single word (4) or double word (8) alignment */
#define ALIGNMENT 8
/* rounds up to the nearest multiple of ALIGNMENT */
#define ALIGN(size) (((size) + (ALIGNMENT-1)) & ~0x7)
#define SIZE_T_SIZE (ALIGN(sizeof(size_t)))
/* Basic constants and macros */
#define WSIZE 4 // Word and header/footer size (bytes)
#define DSIZE 8 // Double word size (bytes)
#define CHUNKSIZE (1 << 12) // Extend heap by this amount (bytes)
#define MAX(x, y) ((x) > (y) ? (x) : (y))
/* Pack a size and allocated bit into a word */
#define PACK(size, alloc) ((size) | (alloc))
/* Read and write a word at address p */
#define GET(p) (*(unsigned int *)(p))
#define PUT(p, val) (*(unsigned int *)(p) = (val))
/* Read the size and allocated fields from address p */
#define GET_SIZE(p) (GET(p) & ~0x7)
#define GET_ALLOC(p) (GET(p) & 0x1)
/* Given block ptr bp, compute address of its header and footer */
#define HDRP(bp) ((char *)(bp)-WSIZE)
#define FTRP(bp) ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE)
/* Given block ptr bp, compute address of next and previous blocks */
#define NEXT_BLKP(bp) ((char *)(bp) + GET_SIZE(((char *)(bp)-WSIZE)))
#define PREV_BLKP(bp) ((char *)(bp)-GET_SIZE(((char *)(bp)-DSIZE)))
/* glbal variable */
static char *heap_listp; // 정적 전역변수를 사용한 할당기
static void *extend_heap(size_t);
static void *coalesce(void *);
static void *find_fit(size_t);
static void place(void *, size_t);
/* mm_init - initialize the malloc package. */
int mm_init(void){
/* Create the initial empty heap */
if ((heap_listp = mem_sbrk(4 * WSIZE)) == (void *)-1)
return -1;
PUT(heap_listp, 0); // Alignment padding
PUT(heap_listp + (1 * WSIZE), PACK(DSIZE, 1)); // Prologue header
PUT(heap_listp + (2 * WSIZE), PACK(DSIZE, 1)); // Prologue footer
PUT(heap_listp + (3 * WSIZE), PACK(0, 1)); // Epilogue header
heap_listp += (2 * WSIZE);
/* Extend the empty heap with a free block of CHUNKSIZE bytes */
if (extend_heap(CHUNKSIZE / WSIZE) == NULL)
return -1;
return 0;
}
static void *extend_heap(size_t words){
char *bp;
size_t size;
/* Allocate an even number of words to maintain alignment */
size = (words % 2) ? (words + 1) * WSIZE : words * WSIZE;
if ((long)(bp = mem_sbrk(size)) == -1)
return NULL;
/* Initialize free block header/footer and the epliogue header */
PUT(HDRP(bp), PACK(size, 0)); // Free block header
PUT(FTRP(bp), PACK(size, 0)); // Free block footer
PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1)); // New epilogue header
/* Coalesce if the previous block was free */
return coalesce(bp);
}
/* mm_malloc - Allocate a block by incrementing the brk pointer. Always allocate a block whose size is a multiple of the alignment. */
void *mm_malloc(size_t size){
size_t asize; // Adjusted block size
size_t extendsize; // Amount to extend heap if no fit
char *bp;
/* Ignore spurious requests */
if (size == 0)
return NULL;
/* Adjust block size to include overhead and alignment reqs. */
if (size <= DSIZE)
asize = 2 * DSIZE;
else
asize = DSIZE * ((size + (DSIZE) + (DSIZE - 1)) / DSIZE);
/* Search the free list for a fit */
if ((bp = find_fit(asize)) != NULL)
{
place(bp, asize);
return bp;
}
/* No fit found. Get more memory ans place the block */
extendsize = MAX(asize, CHUNKSIZE);
if ((bp = extend_heap(extendsize / WSIZE)) == NULL)
return NULL;
place(bp, asize);
return bp;
}
/* mm_free - Freeing a block does nothing. */
void mm_free(void *bp){
size_t size = GET_SIZE(HDRP(bp));
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
coalesce(bp);
}
static void *coalesce(void *bp)
{
size_t prev_alloc = GET_ALLOC(FTRP(PREV_BLKP(bp)));
size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp)));
size_t size = GET_SIZE(HDRP(bp));
if (prev_alloc && next_alloc)
{ // Case 1
return bp;
}
else if (prev_alloc && !next_alloc)
{ // Case 2
size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
}
else if (!prev_alloc && next_alloc)
{ // Case 3
size += GET_SIZE(HDRP(PREV_BLKP(bp)));
PUT(FTRP(bp), PACK(size, 0));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
bp = PREV_BLKP(bp);
}
else
{ // Case 4
size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(FTRP(NEXT_BLKP(bp)));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
bp = PREV_BLKP(bp);
}
return bp;
}
/* mm_realloc - Implemented simply in terms of mm_malloc and mm_free */
void *mm_realloc(void *ptr, size_t size)
{
void *oldptr = ptr;
void *newptr;
size_t copySize;
newptr = mm_malloc(size);
if (newptr == NULL)
return NULL;
// copySize = *(size_t *)((char *)oldptr - SIZE_T_SIZE);
copySize = GET_SIZE(HDRP(oldptr));
if (size < copySize)
copySize = size;
memcpy(newptr, oldptr, copySize);
mm_free(oldptr);
return newptr;
}
static void *find_fit(size_t asize)
{
void *bp;
for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp))
{
if (!GET_ALLOC(HDRP(bp)) && (asize <= GET_SIZE(HDRP(bp))))
{
return bp;
}
}
return NULL; // No fit
}
static void place(void *bp, size_t asize)
{
size_t csize = GET_SIZE(HDRP(bp));
if ((csize - asize) >= (2 * DSIZE))
{
PUT(HDRP(bp), PACK(asize, 1));
PUT(FTRP(bp), PACK(asize, 1));
bp = NEXT_BLKP(bp);
PUT(HDRP(bp), PACK(csize - asize, 0));
PUT(FTRP(bp), PACK(csize - asize, 0));
}
else
{
PUT(HDRP(bp), PACK(csize, 1));
PUT(FTRP(bp), PACK(csize, 1));
}
}
▶ 구현 코드(Next Fit)
/*
* mm-naive.c - The fastest, least memory-efficient malloc package.
*
* In this naive approach, a block is allocated by simply incrementing
* the brk pointer. A block is pure payload. There are no headers or
* footers. Blocks are never coalesced or reused. Realloc is
* implemented directly using mm_malloc and mm_free.
*
* NOTE TO STUDENTS: Replace this header comment with your own header
* comment that gives a high level description of your solution.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include "mm.h"
#include "memlib.h"
/*********************************************************
* NOTE TO STUDENTS: Before you do anything else, please
* provide your team information in the following struct.
********************************************************/
/* single word (4) or double word (8) alignment */
#define ALIGNMENT 8
/* rounds up to the nearest multiple of ALIGNMENT */
#define ALIGN(size) (((size) + (ALIGNMENT-1)) & ~0x7)
#define SIZE_T_SIZE (ALIGN(sizeof(size_t)))
/* Basic constants and macros */
#define WSIZE 4 // Word and header/footer size (bytes)
#define DSIZE 8 // Double word size (bytes)
#define CHUNKSIZE (1 << 12) // Extend heap by this amount (bytes)
#define MAX(x, y) ((x) > (y) ? (x) : (y))
/* Pack a size and allocated bit into a word */
#define PACK(size, alloc) ((size) | (alloc))
/* Read and write a word at address p */
#define GET(p) (*(unsigned int *)(p))
#define PUT(p, val) (*(unsigned int *)(p) = (val))
/* Read the size and allocated fields from address p */
#define GET_SIZE(p) (GET(p) & ~0x7)
#define GET_ALLOC(p) (GET(p) & 0x1)
/* Given block ptr bp, compute address of its header and footer */
#define HDRP(bp) ((char *)(bp)-WSIZE)
#define FTRP(bp) ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE)
/* Given block ptr bp, compute address of next and previous blocks */
#define NEXT_BLKP(bp) ((char *)(bp) + GET_SIZE(((char *)(bp)-WSIZE)))
#define PREV_BLKP(bp) ((char *)(bp)-GET_SIZE(((char *)(bp)-DSIZE)))
/* glbal variable */
static char *heap_listp; // 정적 전역변수를 사용한 할당기
static void *extend_heap(size_t);
static void *coalesce(void *);
static void *next_fit(size_t);
static void place(void *, size_t);
static char* last_bp; // 마지막에 검사한 블록의 포인터
/* mm_init - initialize the malloc package. */
int mm_init(void){
/* Create the initial empty heap */
if ((heap_listp = mem_sbrk(4 * WSIZE)) == (void *) - 1)
return -1;
PUT(heap_listp, 0); // Alignment padding
PUT(heap_listp + (1 * WSIZE), PACK(DSIZE, 1)); // Prologue header
PUT(heap_listp + (2 * WSIZE), PACK(DSIZE, 1)); // Prologue footer
PUT(heap_listp + (3 * WSIZE), PACK(0, 1)); // Epilogue header
heap_listp += (2 * WSIZE);
/* Extend the empty heap with a free block of CHUNKSIZE bytes */
if (extend_heap(CHUNKSIZE / WSIZE) == NULL)
return -1;
return 0;
}
static void *extend_heap(size_t words){
char *bp;
size_t size;
/* Allocate an even number of words to maintain alignment */
size = (words % 2) ? (words + 1) * WSIZE : words * WSIZE;
if ((long)(bp = mem_sbrk(size)) == -1)
return NULL;
/* Initialize free block header/footer and the epliogue header */
PUT(HDRP(bp), PACK(size, 0)); // Free block header
PUT(FTRP(bp), PACK(size, 0)); // Free block footer
PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1)); // New epilogue header
/* Coalesce if the previous block was free */
return coalesce(bp);
}
/* mm_malloc - Allocate a block by incrementing the brk pointer. Always allocate a block whose size is a multiple of the alignment. */
void *mm_malloc(size_t size){
size_t asize; // Adjusted block size
size_t extendsize; // Amount to extend heap if no fit
char *bp;
/* Ignore spurious requests */
if (size == 0)
return NULL;
/* Adjust block size to include overhead and alignment reqs. */
if (size <= DSIZE)
asize = 2 * DSIZE;
else
asize = DSIZE * ((size + (DSIZE) + (DSIZE - 1)) / DSIZE);
/* Search the free list for a fit */
if ((bp = next_fit(asize)) != NULL){
place(bp, asize);
return bp;
}
/* No fit found. Get more memory ans place the block */
extendsize = MAX(asize, CHUNKSIZE);
if ((bp = extend_heap(extendsize / WSIZE)) == NULL)
return NULL;
place(bp, asize);
return bp;
}
/* mm_free - Freeing a block does nothing. */
void mm_free(void *bp){
size_t size = GET_SIZE(HDRP(bp));
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
coalesce(bp);
}
static void *coalesce(void *bp)
{
size_t prev_alloc = GET_ALLOC(FTRP(PREV_BLKP(bp)));
size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp)));
size_t size = GET_SIZE(HDRP(bp));
if (prev_alloc && next_alloc)
{ // Case 1
last_bp =bp;
return bp;
}
else if (prev_alloc && !next_alloc)
{ // Case 2
size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
}
else if (!prev_alloc && next_alloc)
{ // Case 3
size += GET_SIZE(HDRP(PREV_BLKP(bp)));
PUT(FTRP(bp), PACK(size, 0));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
bp = PREV_BLKP(bp);
}
else
{ // Case 4
size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(FTRP(NEXT_BLKP(bp)));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
bp = PREV_BLKP(bp);
}
last_bp = bp;
return bp;
}
/* mm_realloc - Implemented simply in terms of mm_malloc and mm_free */
void *mm_realloc(void *ptr, size_t size)
{
void *oldptr = ptr;
void *newptr;
size_t copySize;
newptr = mm_malloc(size);
if (newptr == NULL)
return NULL;
copySize = GET_SIZE((char *)oldptr - WSIZE) - DSIZE; // header의 사이즈
if (size < copySize) {
copySize = size;
}
memcpy(newptr, oldptr, copySize);
mm_free(oldptr);
return newptr;
}
static void* next_fit(size_t asize)
{
char* bp = last_bp;
while (GET_SIZE(HDRP(bp))!=0) {
bp = NEXT_BLKP(bp);
if (GET_ALLOC(HDRP(bp)) == 0 && GET_SIZE(HDRP(bp)) >= asize)
{
last_bp = bp;
return bp;
}
}
bp = heap_listp;
while (bp < last_bp)
{
bp = NEXT_BLKP(bp);
if (GET_ALLOC(HDRP(bp)) == 0 && GET_SIZE(HDRP(bp)) >= asize)
{
last_bp = bp;
return bp;
}
}
return NULL ;
}
static void place(void *bp, size_t asize)
{
size_t csize = GET_SIZE(HDRP(bp));
if ((csize - asize) >= (2 * DSIZE))
{
PUT(HDRP(bp), PACK(asize, 1));
PUT(FTRP(bp), PACK(asize, 1));
bp = NEXT_BLKP(bp);
PUT(HDRP(bp), PACK(csize - asize, 0));
PUT(FTRP(bp), PACK(csize - asize, 0));
}
else
{
PUT(HDRP(bp), PACK(csize, 1));
PUT(FTRP(bp), PACK(csize, 1));
}
}
'컴퓨터 시스템 > CSAPP' 카테고리의 다른 글
동적 메모리 할당 - malloc 함수 구현(분리 가용 리스트) (0) | 2021.12.15 |
---|---|
동적 메모리 할당 - malloc 함수 구현(명시적 가용 리스트 이용) (0) | 2021.12.13 |
가상 메모리 (0) | 2021.12.10 |
동적 메모리 할당과 할당기 (0) | 2021.12.09 |
운영체제 (0) | 2021.12.09 |