<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>gyojin-bot.log</title>
        <link>https://velog.io/</link>
        <description>코딩 벌레가 되어보자</description>
        <lastBuildDate>Wed, 20 Jan 2021 12:14:34 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>gyojin-bot.log</title>
            <url>https://images.velog.io/images/gyojin-bot/profile/8e3eb001-cf56-48e7-8f9e-c3e717882549/social.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. gyojin-bot.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/gyojin-bot" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Malloc LAB - Implicit (final)]]></title>
            <link>https://velog.io/@gyojin-bot/Malloc-LAB-2-Implicit-Next-fit</link>
            <guid>https://velog.io/@gyojin-bot/Malloc-LAB-2-Implicit-Next-fit</guid>
            <pubDate>Wed, 20 Jan 2021 12:14:34 GMT</pubDate>
            <description><![CDATA[<hr>
<ul>
<li>채점 결과
<img src="https://images.velog.io/images/gyojin-bot/post/82091347-bc8d-4f80-aad5-11443290466c/image.png" alt=""></li>
</ul>
<hr>
<ul>
<li>코드<pre><code class="language-c">/*
* 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 &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;assert.h&gt;
#include &lt;unistd.h&gt;
#include &lt;string.h&gt;
</code></pre>
</li>
</ul>
<p>#include &quot;mm.h&quot;
#include &quot;memlib.h&quot;</p>
<p>/<strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>*****</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></p>
<ul>
<li>NOTE TO STUDENTS: Before you do anything else, please</li>
<li>provide your team information in the following struct.</li>
<li><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>***</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong>/
team_t team = {
  /* Team name <em>/
  &quot;ateam&quot;,
  /</em> First member&#39;s full name <em>/
  &quot;Choi Gyojin&quot;,
  /</em> First member&#39;s email address <em>/
  &quot;<a href="mailto:choi1036mk@gmail.com">choi1036mk@gmail.com</a>&quot;,
  /</em> Second member&#39;s full name (leave blank if none) <em>/
  &quot;&quot;,
  /</em> Second member&#39;s email address (leave blank if none) */
  &quot;&quot;};</li>
</ul>
<p>/* single word (4) or double word (8) alignment */
#define ALIGNMENT 8</p>
<p>/* rounds up to the nearest multiple of ALIGNMENT */
#define ALIGN(size) (((size) + (ALIGNMENT - 1)) &amp; ~0x7)
#define SIZE_T_SIZE (ALIGN(sizeof(size_t)))</p>
<p>/* Basic constants and macros <em>/
#define WSIZE 4             /</em> Word and header/footer size (bytes) <em>/
#define DSIZE 8             /</em> Double word size (bytes) <em>/
#define CHUNKSIZE (1 &lt;&lt; 12) /</em> Extend heap by this amount (bytes) */</p>
<p>#define MAX(x, y) ((x) &gt; (y) ? (x) : (y))</p>
<p>/* Pack a size and allocated bit into a word */
#define PACK(size, alloc) ((size) | (alloc))</p>
<p>/* Read and write a word at address p <em>/
#define GET(p) (</em>(unsigned int <em>)(p))
#define PUT(p, val) (</em>(unsigned int *)(p) = (val))</p>
<p>/* Read the size and allocated fields from address p */
#define GET_SIZE(p) (GET(p) &amp; ~0x7)
#define GET_ALLOC(p) (GET(p) &amp; 0x1)</p>
<p>/* 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)</p>
<p>/* 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)))</p>
<p>/* The only global variable is a pointer to the first block */
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);</p>
<p>/* </p>
<ul>
<li><p>mm_init - initialize the malloc package.</p>
</li>
<li><p>/
int mm_init(void)
{
  /* Create the initial empty heap */
  if ((heap_listp = mem_sbrk(4 * WSIZE)) == (void *)-1)</p>
<pre><code>  return -1;</code></pre><p>  PUT(heap_listp, 0);                            /* Alignment padding <em>/
  PUT(heap_listp + (1 * WSIZE), PACK(DSIZE, 1)); /</em> Prologue header <em>/
  PUT(heap_listp + (2 * WSIZE), PACK(DSIZE, 1)); /</em> Prologue footer <em>/
  PUT(heap_listp + (3 * WSIZE), PACK(0, 1));     /</em> Epilogue header */
  heap_listp += (2 * WSIZE);</p>
<p>  /* Extend the empty heap with a free block of CHUNKSIZE bytes */
  if (extend_heap(CHUNKSIZE / WSIZE) == NULL)</p>
<pre><code>  return -1;</code></pre><p>  return 0;
}</p>
</li>
</ul>
<p>static void *extend_heap(size_t words)
{
    char *bp;
    size_t size;</p>
<pre><code>/* 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 epilogue 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);</code></pre><p>}</p>
<p>/* </p>
<ul>
<li><p>mm_malloc - Allocate a block by incrementing the brk pointer.</p>
</li>
<li><p>Always allocate a block whose size is a multiple of the alignment.</p>
</li>
<li><p>/
void <em>mm_malloc(size_t size)
{
  size_t asize;      /</em> Adjusted block size <em>/
  size_t extendsize; /</em> Amount to extend heap if no fit <em>/
  char *bp;
  /</em> Ignore spurious requests */
  if (size == 0)</p>
<pre><code>  return NULL;</code></pre><p>  /* Adjust block size to include overhead and alignment reqs. */
  if (size &lt;= DSIZE)</p>
<pre><code>  asize = 2 * DSIZE;</code></pre><p>  else</p>
<pre><code>  asize = DSIZE * ((size + (DSIZE) + (DSIZE - 1)) / DSIZE);</code></pre><p>  /* Search the free list for a fit */
  if ((bp = find_fit(asize)) != NULL)
  {</p>
<pre><code>  place(bp, asize);
  return bp;</code></pre><p>  }</p>
<p>  /* No fit found. Get more memory and place the block */
  extendsize = MAX(asize, CHUNKSIZE);
  if ((bp = extend_heap(extendsize / WSIZE)) == NULL)</p>
<pre><code>  return NULL;</code></pre><p>  place(bp, asize);
  return bp;
}</p>
</li>
</ul>
<p>/*</p>
<ul>
<li>mm_free - Freeing a block does nothing.</li>
<li>/
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);
}</li>
</ul>
<p>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));</p>
<pre><code>if (prev_alloc &amp;&amp; next_alloc)
{ /* Case 1 */
    return bp;
}

else if (prev_alloc &amp;&amp; !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 &amp;&amp; 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;</code></pre><p>}</p>
<p>/*</p>
<ul>
<li><p>mm_realloc - Implemented simply in terms of mm_malloc and mm_free</p>
</li>
<li><p>/
void *mm_realloc(void *ptr, size_t size)
{
  void *oldptr = ptr;
  void *newptr;
  size_t copySize;</p>
<p>  newptr = mm_malloc(size);
  if (newptr == NULL)</p>
<pre><code>  return NULL;</code></pre><p>  copySize = GET_SIZE(HDRP(oldptr));</p>
<p>  if (size &lt; copySize)
  {</p>
<pre><code>  copySize = size;</code></pre><p>  }</p>
<p>  memcpy(newptr, oldptr, copySize);
  mm_free(oldptr);
  return newptr;
}</p>
</li>
</ul>
<p>static void <em>find_fit(size_t asize)
{
    /</em> next-fit search */
    char *bp;</p>
<pre><code>// Search from next_fit to the end of the heap
for (bp = heap_listp; GET_SIZE(HDRP(bp)) &gt; 0; bp = NEXT_BLKP(bp))
{
    if (!GET_ALLOC(HDRP(bp)) &amp;&amp; (asize &lt;= GET_SIZE(HDRP(bp))))
    {
        // If a fit is found, return the address the of block pointer
        return bp;
    }
}

return NULL; /* No fit */</code></pre><p>}</p>
<p>static void place(void *bp, size_t asize)
{
    size_t csize = GET_SIZE(HDRP(bp));
    if ((csize - asize) &gt;= (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));
    }
}</p>
<p>```</p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[Malloc LAB - Implicit (2)]]></title>
            <link>https://velog.io/@gyojin-bot/Malloc-LAB-Implicit-2</link>
            <guid>https://velog.io/@gyojin-bot/Malloc-LAB-Implicit-2</guid>
            <pubDate>Wed, 20 Jan 2021 11:10:33 GMT</pubDate>
            <description><![CDATA[<p>지난 포스팅에 이어 묵시적 할당기를 마저 구현해보자.</p>
<h3 id="mm_realloc">mm_realloc</h3>
<p><code>mm_realloc</code>은 기존에 할당되어 있던 블록을 새로운 사이즈로 재할당하는 함수이다.</p>
<p>여기에는 2가지 경우가 고려되어야 한다.</p>
<blockquote>
</blockquote>
<ol>
<li>새로 할당하려는 size가 기존 size보다 작을 때<pre><code> **- 기존 정보를 일부만 복사한 뒤 새로운 포인터를 반환**</code></pre></li>
</ol>
<blockquote>
</blockquote>
<ol start="2">
<li>새로 할당하려는 size가 기존 size보다 클 때<pre><code> **- 기존 정보를 모두 복사한 뒤 새로운 포인터를 반환**</code></pre></li>
</ol>
<hr>
<ul>
<li><code>mm_realloc</code><pre><code class="language-c">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(HDRP(oldptr));
  if (size &lt; copySize)
  {
      copySize = size;
  }
  memcpy(newptr, oldptr, copySize);
  mm_free(oldptr);
  return newptr;
}
</code></pre>
</li>
</ul>
<pre><code>***

### place

`place` 함수는 블록이 할당되거나 재할당될 때 여유 공간을 판단하여 분할해 주는 함수이다.

여기에도 2가지 경우가 있을 수 있다.

&gt;
1. 현재 블록에 size를 할당한 후에 남은 size가 최소 블록 size(`header`와 `footer`를 포함한 4워드)보다 크거나 같을 때
        **- 현재 블록의 size 정보를 변경하고 남은 size를 새로운 가용 블록으로 분할한다**

&gt;
2. 현재 블록에 size를 할당한 후에 남은 size가 최소 블록 size보다 작을 때
        **- 현재 블록의 size 정보만 바꿔준다**

***
* `place`
```c
static void place(void *bp, size_t asize)
{
    size_t csize = GET_SIZE(HDRP(bp));
    if ((csize - asize) &gt;= (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));
    }
}
</code></pre><hr>
<p>여기까지 완성하면 Implicit malloc 프로그램을 정상적으로 구동할 수 있게 된다.</p>
<h3 id="👏-til">👏 TIL</h3>
<p>컴퓨터시스템 교재의 9.9장을 참고하여 따라오면 그대로 구현할 수 있었고 책 내용을 구글링하여 찾아보고 직접 실습해본 내용을 재구성하여 정리하였다.</p>
<p>malloc을 함수로만 사용해 보다가 할당기를 직접 구현하여 보니 시스템의 밑단에서 상당히 복잡한 작업이 이루어지고 있다는 점을 배우게 되었다.</p>
<p>first fit 방식으로 구현하였는데 이를 next fit이나 best fit으로 최적화하는 방법도 있고, 묵시적 할당기가 아닌 명시적 할당기 (Explicit) 방법도 이후에 구현해볼 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 2075번 N번째 큰 수]]></title>
            <link>https://velog.io/@gyojin-bot/2-%EB%B0%B1%EC%A4%80-2075%EB%B2%88-N%EB%B2%88%EC%A7%B8-%ED%81%B0-%EC%88%98</link>
            <guid>https://velog.io/@gyojin-bot/2-%EB%B0%B1%EC%A4%80-2075%EB%B2%88-N%EB%B2%88%EC%A7%B8-%ED%81%B0-%EC%88%98</guid>
            <pubDate>Wed, 20 Jan 2021 05:22:49 GMT</pubDate>
            <description><![CDATA[<p>슬라이딩 윈도우 방식으로 풀이해보려 하였으나, 생각해 보니 우선순위 큐를 이용해서 접근하는 것이 거의 유사한 방법론으로 보여서 시도하였다.</p>
<blockquote>
<p>슬라이딩 윈도우 (최댓값 찾기 예시)</p>
</blockquote>
<ul>
<li>0행과 1행의 정보를 비교하여 최댓값을 저장한다.</li>
<li>이후에는 그 결과와 2행의 정보를 비교하면서 예전에 탐색했던 0행의 정보를 다시 들춰보지 않도록 &quot;창문&quot; 형태로 구간을 이동시킨다. </li>
</ul>
<p>처음 로직은 <code>heap</code>의 크기를 5로 유지하면서, 가장 큰 수보다 더 큰 수가 탐색되었을 때 <code>heap</code>에 밀어넣어 주는 방식이었다.</p>
<p>메모리를 줄이는 것이 관건이었는데, 주어진 표를 저장하면 4byte * (N x N) 이고, 최대 N이 1500이므로 공간복잡도는
$$
4 * 1500 * 1500 = 9000000(byte)
$$
약 9MB를 차지하여, 충분하다고 보았다. 하지만 여기서 메모리 초과가 발생하게 되는데,,
<code>pypy</code>로 시도하면 돌아가긴 하나 <code>index error</code>가 발생했다.<br>
아무래도 <code>python3</code>로 채점 시 기본적으로 차지하는 메모리 공간이 존재하는 듯하다. (라이브러리 탓인지도 모르겠다)</p>
<hr>
<p><img src="https://images.velog.io/images/gyojin-bot/post/2f500695-61a4-4511-bc03-1faee9b5d060/image.png" alt=""></p>
<pre><code class="language-python">import sys
import heapq

N = int(sys.stdin.readline())
table = []

for _ in range(N):
    table.append(list(map(int, sys.stdin.readline().split())))

maxi = table[0][0]
heap = []
for i in range(N):
    for j in range(N):
        if table[i][j] &gt; maxi:
            heapq.heappush(heap, table[i][j])
        if len(heap) &gt; N:
            heapq.heappop(heap)


print(heap[0])</code></pre>
<hr>
<p><code>pypy</code>에서 무엇이 문제였을고 하니 N이 1일 경우에, 그러니까 <code>maxi</code>가 정답 자체일 경우에 <code>heap</code>에 아무것도 저장되지 않기 때문에 마지막 <code>print</code>가 <code>index error</code>를 마주치는 것이었다..!</p>
<p>하여 아래와 같이 수정하였다. (<code>table</code>도 바로바로 받는 형태로 구성했다)</p>
<hr>
<pre><code class="language-python">import sys
import heapq

N = int(sys.stdin.readline())
heap = []

for _ in range(N):
    table = list(map(int, sys.stdin.readline().split()))

    for item in table:
        heapq.heappush(heap, item)
        if len(heap) &gt; N:
            heapq.heappop(heap)

print(heap[0])</code></pre>
<hr>
<p>이리하여 통과가 되었고, 상위권 정답코드를 보니 훨씬 깔끔하다.
다소 원초적인 방법일 수 있으나, <code>table</code>에 첫 행을 저장해 두고 다음 행을 <code>table</code> 뒤에 붙인 뒤 역순 정렬하여 가장 큰 5개의 수만 남겨두는 형태이다. 이게 되네? 느낌</p>
<hr>
<pre><code class="language-python">import sys

N = int(sys.stdin.readline())
table = list(map(int, sys.stdin.readline().split()))

for _ in range(N - 1):
    table += list(map(int, sys.stdin.readline().split()))
    table = sorted(table, reverse=True)[:N]

print(table[N-1])</code></pre>
<hr>
<h2 id="til">TIL</h2>
<p>매 행을 계속 비교하게 되면 자칫 $O(N^2)$의 시간복잡도를 가질 수 있는 것을 우선순위큐를 이용해서 $Nlog(N)$의 시간복잡도로 개선할 수 있음을 배웠다. 다만, 의외로 간단하게 생각하면 더 쉽고 빠른 알고리즘을 고안할 수 있을 것 같다. 붙이고 자르는 방식이라니... 상상조차 못했다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Malloc LAB - Implicit (1)]]></title>
            <link>https://velog.io/@gyojin-bot/Malloc-LAB-1</link>
            <guid>https://velog.io/@gyojin-bot/Malloc-LAB-1</guid>
            <pubDate>Tue, 19 Jan 2021 11:07:27 GMT</pubDate>
            <description><![CDATA[<p><strong>Malloc이란? C언어의 동적 메모리 할당을 의미합니다. (Dynamic Memory Allocation)</strong></p>
<ul>
<li><p>예를 들어 배열의 크기를 미리 알수 없다면? 어떻게 메모리를 할당해줘야 할까요?</p>
<p>  → 이 때 쓰이는 것이 &#39;동적 메모리 할당&#39;</p>
</li>
<li><p>implicit, explicit, seglist 등 여러 방법이 있지만, 우리는 <code>implicit</code> 방법을 이용해서 랩을 수행하겠습니다. 여유가 되면 explicit 까지도 도전해보세요.</p>
</li>
</ul>
<h2 id="말록랩-과제-설명"><strong>말록랩 과제 설명</strong></h2>
<ul>
<li><a href="http://csapp.cs.cmu.edu/3e/malloclab.pdf">http://csapp.cs.cmu.edu/3e/malloclab.pdf</a></li>
<li>출처: CMU (카네기멜론)</li>
</ul>
<h3 id="참고자료"><strong>참고자료</strong></h3>
<ul>
<li><a href="http://csapp.cs.cmu.edu/3e/labs.html">http://csapp.cs.cmu.edu/3e/labs.html</a></li>
<li>CMU 강의자료 전체</li>
</ul>
<h3 id="기본-할당기-설계">기본 할당기 설계</h3>
<p>주어진 파일 리스트의 memlib.c 파일을 살펴보면 할당기의 기본적인 설계를 볼 수 있다.</p>
<hr>
<ol>
<li><code>mem_init</code></li>
</ol>
<ul>
<li><code>mem_start_brk</code> : 힙의 시작점</li>
<li><code>mem_max_addr</code> : 가능한 legal heap의 끝 주소</li>
<li><code>mem_brk</code> : 힙의 종료점
(init 단계에서는 heap이 비어 있으므로 <code>mem_start_brk</code>와 같다.</li>
</ul>
<ol start="2">
<li><code>mem_sbrk</code></li>
</ol>
<ul>
<li>추가 힙 메모리를 요청하고 성공하면 기존 힙의 시작점 주소를, 아니면 -1을 리턴한다.</li>
</ul>
<hr>
<h2 id="implicit-malloc">Implicit Malloc</h2>
<p><code>mm.c</code> 파일에서 조작해야 할 함수는 아래와 같다.
(본 글에서는 6번까지 구현할 예정)</p>
<blockquote>
</blockquote>
<ol>
<li><code>mm_init</code></li>
<li><code>extend_heap</code></li>
<li><code>mm_free</code></li>
<li><code>coalesce</code></li>
<li><code>mm_malloc</code></li>
<li><code>find_fit</code></li>
<li><code>mm_realloc</code></li>
<li><code>place</code></li>
</ol>
<h3 id="mm_init">mm_init</h3>
<p>할당기의 초기화 함수. 묵시적 가용 리스트는 아래와 같은 구조를 가지고 있다.</p>
<p><img src="https://images.velog.io/images/gyojin-bot/post/917cafeb-90a7-41e7-a61f-e1afaf4f1ca9/image.png" alt=""></p>
<ul>
<li><p><code>Header</code> : 블록의 할당 여부와 크기를 저장한다.</p>
</li>
<li><p><code>Payload</code> : 할당된 블록에만 값이 들어있다.</p>
</li>
<li><p><code>Padding</code> : Double Word 정렬을 위해 붙여 주는 공간.</p>
</li>
<li><p><strong><code>Footer</code></strong> : 경계 태그로 사용되며, <code>Header</code>의 값이 복사되어 있다. 블록을 반환할 때 이전 블록을 상수 시간 내에 탐색할 수 있도록 하는 장치.</p>
<p>  (<code>Footer</code>가 없으면 모든 블록의 size 정보가 다르기 때문에 이전 <code>Header</code>를 찾아내기 위해서는 힙의 시작점부터 순차적으로 탐색해야 하는 불편이 생긴다)</p>
</li>
</ul>
<p><img src="https://images.velog.io/images/gyojin-bot/post/8478f6a5-7109-4369-862c-a15bb9cd04ee/image.png" alt=""></p>
<ol>
<li>위의 블록 구조를 참고하여, 프롤로그 블록 + 에필로그 블록을 초기화 시 할당한다. 이 블록은 <code>Header</code>와 <code>Footer</code>로 구성된 8바이트 할당 블록이며, 할당기 프로그램이 종료될 때까지 반환되지 않는다. (이유는 경계 조건을 무시하기 위해)</li>
<li>또한 Double Word 정렬을 위해 사용하지 않는 패딩 블록을 맨 앞에 붙여놓는다.</li>
<li>힙이 확장될 때 에필로그 블록은 확장된 힙의 마지막에 위치하도록 한다.</li>
</ol>
<hr>
<ul>
<li><code>mm_init</code></li>
</ul>
<pre><code class="language-c">int mm_init(void)
{
    /* Create the initial empty heap */
    if ((heap_listp = mem_sbrk(4 * WSIZE)) == (void *)-1)
        return -1;
    PUT(heap_listp, PACK(DSIZE, 1));               /* 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 ** when find func, note endpoint */
    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;
}</code></pre>
<hr>
<h3 id="extend_heap">extend_heap</h3>
<p>이 함수는 2가지 경우에 호출될 수 있다.</p>
<blockquote>
</blockquote>
<ol>
<li><strong>힙이 초기화될 때</strong>
초기화 후에 초기 가용 블록을 생성하기 위해 호출된다.</li>
</ol>
<blockquote>
</blockquote>
<ol start="2">
<li>요청한 크기의 메모리 할당을 위해 <strong>충분한 공간을 찾지 못했을 때</strong>
Double word 정렬을 위해 8의 배수로 반올림하고, 추가 힙 공간을 요청한다.</li>
</ol>
<hr>
<ul>
<li><code>extend_heap</code></li>
</ul>
<pre><code class="language-c">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 epilogue 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);
}</code></pre>
<hr>
<h3 id="mm_free--coalesce">mm_free / coalesce</h3>
<p>블록을 반환하고(= <code>mm_free</code>) 경계 태그(<code>Header</code>, <code>Footer</code>)를 사용해서 상수 시간 내에 인접한 가용 블록(free)들과 통합한다. (= <code>coalesce</code>)</p>
<p>여기서는 4가지 Case가 존재한다.</p>
<blockquote>
</blockquote>
<ul>
<li>Case 1 : 이전과 다음 블록이 모두 할당되어 있다.
  <strong>- 현재 블록만 가용 상태로 변경한다.</strong></li>
</ul>
<blockquote>
</blockquote>
<ul>
<li>Case 2 : 이전 블록은 할당 상태, 다음 블록은 가용 상태이다.
  <strong>- 현재 블록과 다음 블록을 통합한다.</strong></li>
</ul>
<blockquote>
</blockquote>
<ul>
<li>Case 3 : 이전 블록은 가용 상태, 다음 블록은 할당 상태이다.
   <strong>- 이전 블록과 현재 블록을 통합한다.</strong></li>
</ul>
<blockquote>
</blockquote>
<ul>
<li>Case 4 : 이전 블록과 다음 블록 모두 가용 상태이다.
  <strong>- 이전 블록, 현재 블록, 다음 블록을 통합한다.</strong></li>
</ul>
<p><img src="https://images.velog.io/images/gyojin-bot/post/df390561-907d-4b6a-8a10-3c7c17b1b2ff/image.png" alt=""></p>
<p>프롤로그와 에필로그를 할당 상태로 초기화했기 때문에, <code>free</code>를 요청한 블록의 주소 <code>bp</code>가 힙의 시작 부분 또는 끝 부분에 위치하는 경계조건(Edge Condition)을 무시할 수 있게 된다.</p>
<hr>
<ul>
<li><code>mm_free</code> / <code>coalesce</code><pre><code class="language-c">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);
}
</code></pre>
</li>
</ul>
<p>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));</p>
<pre><code>if (prev_alloc &amp;&amp; next_alloc)
{ /* Case 1 */
    return bp;
}

else if (prev_alloc &amp;&amp; !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 &amp;&amp; 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;</code></pre><p>}</p>
<pre><code>***

### mm_malloc / find_fit

요청한 size 만큼의 공간이 있는 메모리 블록을 할당하는 함수. 아래의 기능을 구현한다.

- `Header`와 `Footer` 공간을 위해 최소 16bytes(4워드)의 크기를 유지하도록 한다.
- Double Word 정렬을 유지하기 위해 8의 배수로 반올림한 메모리 크기를 할당한다.
- 메모리 할당 크기를 조절한 후, 가용 블록 리스트를 검색하여 적합한 블록을 찾았을 때 배치한다.
    - `find_fit` 함수
    - 여기에서는 First Fit 방식을 사용한다.
    &gt;가용 상태이고, 요청한 사이즈만큼 충분한 공간이 있을 때 해당 블록 포인터(`bp`)를 반환

- OPTION : 찾은 블록에 배치한 후 여유공간이 충분하다면 분할한다. (= `place`)
***
- `mm_malloc`
```c
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 &lt;= 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 and place the block */
    extendsize = MAX(asize, CHUNKSIZE);
    if ((bp = extend_heap(extendsize / WSIZE)) == NULL)
        return NULL;
    place(bp, asize);
    return bp;
}</code></pre><hr>
<ul>
<li><p><code>find_fit</code></p>
<pre><code class="language-c">static void *find_fit(size_t asize)
{
  /* first-fit search */
  char *bp;

  // start the search from the beginning of the heap
  for (bp = heap_listp; GET_SIZE(HDRP(bp)) &gt; 0; bp = NEXT_BLKP(bp))
  {
      if (!GET_ALLOC(HDRP(bp)) &amp;&amp; (asize &lt;= GET_SIZE(HDRP(bp))))
      {
          return bp;
      }
  }
  return NULL; /* No fit */
}</code></pre>
</li>
</ul>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[SW사관학교정글 Essay]]></title>
            <link>https://velog.io/@gyojin-bot/SW%EC%82%AC%EA%B4%80%ED%95%99%EA%B5%90%EC%A0%95%EA%B8%80-Essay</link>
            <guid>https://velog.io/@gyojin-bot/SW%EC%82%AC%EA%B4%80%ED%95%99%EA%B5%90%EC%A0%95%EA%B8%80-Essay</guid>
            <pubDate>Thu, 17 Dec 2020 06:49:24 GMT</pubDate>
            <description><![CDATA[<h3 id="입소한지-1주일-째의-밤이-깊어가고-있다">입소한지 1주일 째의 밤이 깊어가고 있다.</h3>
<p>첫 이틀 동안 웹서버 프로젝트를 하면서 꿈같이 지나갔던 시간이 이제 피부로 느껴진다.</p>
<p>매일 잠들고 일어나고 밥먹으면서도 해야 할 일을 떠올리는 일과가 이제는 평범한 하루가 되었다.</p>
<p>퇴사까지 결심하면서 바라고 기대했던 무언가는 있었지만, 이 곳에서 찾을 수 있을지는 아직 확신이 없다.</p>
<p>프로그래밍에서는 누구보다 처음이지만 누구보다 열심인 것 같지는 않았기 때문이다.</p>
<p>정글을 지원하면서 인터뷰 때도 말했었지만 무슨 일이든지 해보지 않으면 모른다는 생각으로 이곳에 왔다.</p>
<p>5개월 동안 생각했던 것보다 더 고생길이 열린 것 같지만 개발의 길을 걸을 수 있을지 알 수 있다면</p>
<p>그걸로도 훌륭하고 충분한 투자가 아닐까 생각한다.</p>
<p>부족한 부분이 너무 많고 알고 싶은 내용도 많은데, 구글링과 머리에 의지하다 보니 종종 한계가 찾아온다.</p>
<p>열심히 하는 동기들을 보면서 자극도 받지만, 그만큼 모자란 내 자신과 비교하게 된다.</p>
<p>주차가 더해갈수록 버텨내야 하는 것들이 많아질 텐데 벌써부터 지치지 말자고 스스로 다독인다.</p>
<p>오늘 잠시 다녀온 서울이 벌써 그립고 두고 온 것들이 떠오르는 건 어쩔 수 없을 것 같다.</p>
<p>더 성장한 나를 기대한다.</p>
<p>중간에 포기하는 사람 없이, 모두가 끝까지 정글을 걸어나갈 것을 기대한다.</p>
<p>그러고 나면 앞으로 무엇을 할지, 무엇을 할 수 있을지 뚜렷하게 보이지 않을까 한다.</p>
]]></description>
        </item>
    </channel>
</rss>