티스토리 뷰

카테고리 없음

[ malloc.c ] __int_malloc

mhibio 2019. 10. 24. 14:36

_int_malloc 분석입니다.

 

Flow

분석을 하기전에 _int_malloc의 할당과정 요약 입니다.

 

1. 변수 할당
 
2. 아레나가 없다면 sysmalloc으로 아레나를 할당해준다.
 
3. fast size 요청이 들어오면 fast bin 에서 적절한 chunk를 확인하고 있다면 할당해준다.
 
4. small size 요청이 들어오면 small bin 에서 적절한 chunk를 확인하고 있다면 할당해준다.
 
5, largebin 요청이 들어오면 fast bin chunk들을 병합해버린다.
 
+ 3~5 과정에서 적절한 chunk를 찾지 못했다면 다음과정을 거쳐줍니다.
 
6. unsorted bin 에서 size > request size 의 chunk를 찾고, split 후 적절한 크기를 반환해줍니다.
 
7. large bin 에서 size > request size 의 chunk를 찾고, split 후  적절한 크기를 반환해줍니다.
 
8. binmap에서 확장된 bin list에서 사용가능한 chunk를 찾아봅니다.
 
+ 3~8 과정에서 적절한 chunk를 찾지 못했다면 다음과정을 거쳐줍니다.
 
9. top chunk에서 split 한뒤 할당, 반환 해줍니다.
 

 

 

Process 3~5 vs Process 6~8

process 3~5와 6~8은 bin들을 탐색하고 할당해 준다는 부분에 있어서 비슷하지만, 해당 과정은 매우 다릅니다.

3~5과정은 분할없이 바로 반환가능한 chunk를 골라서 반환해주는과정이며

6~8과정은 분할을 한뒤 남길 chunk와 반환할 chunk를 골라서 반환해 주는 과정입니다.

 

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
static void *
_int_malloc (mstate av, size_t bytes)
{
  INTERNAL_SIZE_T nb;               /* 정상적인 요청 크기 */
  unsigned int idx;                 /* 해당 bin의 idx */
  mbinptr bin;                      /* 해당 bin */
 
  mchunkptr victim;                 /* 해당 chunk */
  INTERNAL_SIZE_T size;             /* 해당 size */
  int victim_index;                 /* bin idx */
 
  mchunkptr remainder;              /* 분할 하고 남은 remainder */
  unsigned long remainder_size;     /* 해당 size */
 
  unsigned int block;               /* bit map traverser */
  unsigned int bit;                 /* bit map traverser */
  unsigned int map;                 /* current word of binmap */
 
  mchunkptr fwd;                    /* fd */
  mchunkptr bck;                    /* bk */
 
  const char *errstr = NULL;

변수 선언부입니다.

 

1
2
3
4
5
6
7
8
9
10
11
  checked_request2size (bytes, nb);
  // nb에 요청된 byte를 넣어준다.
 
  if (__glibc_unlikely (av == NULL)) // av가 NULL 값이라면
    {
      void *= sysmalloc (nb, av); // sysmalloc을 통해 p에 할당해준다.
      
      if (p != NULL// sysmalloc이 제대로 되지 않았다면
        alloc_perturb (p, bytes); // alloc_perturb를 호출해준다.
      return p;
    }

sysmalloc을 통해 새로운 아레나를 할당하는 과정입니다.

 

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
31
32
33
34
35
36
37
38
39
40
  if ((unsigned long) (nb) <= (unsigned long) (get_max_fast ())) // 만약 요청된 size가 fastbin의 max_size보다 작다면
    {
      /* fastbin에서 재사용 할만한 chunk가 있는지 확인하는 코드 */
 
      idx = fastbin_index (nb);  // 해당 크기에 맞는 idx를 구해서 val idx에 저장
      mfastbinptr *fb = &fastbin (av, idx);
      mchunkptr pp = *fb;
      // 해당 list에 있는 첫번째 chunk를 받아온다.
 
      do
        {
          victim = pp;
          if (victim == NULL)
            break;
        }while ((pp = catomic_compare_and_exchange_val_acq (fb, victim->fd, victim)) != victim);
      // victim에 해당 bin list에 linked 되어있는 chunk들을 한번씩 넣어주면서 모두 훑을 때까지 반복한다.
      
      if (victim != 0)
        // victim 이 존재한다면
        {
          if (__builtin_expect (fastbin_index (chunksize (victim)) != idx, 0))
            {
              errstr = "malloc(): memory corruption (fast)";
            errout:
              malloc_printerr (check_action, errstr, chunk2mem (victim), av);
              return NULL;
            } 
          /* victim의 size가 해당 fastbin size가 맞는지 확인하고 오류가 발생한다면 에러를 출력한다. */
 
          check_remalloced_chunk (av, victim, nb);
          // remalloc 루틴을 거쳐준다. 분석 X
 
          void *= chunk2mem (victlim); 
          // chunk addr을 인자로 받고, header size를 포함한 사이즈로 설정해준다 ( +8 or +16 bytes )
          alloc_perturb (p, bytes);
          return p;
          // p를 인자로 alloc_perturb를 호출하고 반환해준다.
        }
    }

fastbin에서 쓸만한 chunk를 check합니다.

 

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
31
32
33
34
35
36
37
38
39
40
  // small bin size의 요청이 들어왔을 때 해당 bin을 확인합니다. 
    
  if (in_smallbin_range (nb))
    // request size가 small bin 범위에 있다면
    {
      idx = smallbin_index (nb); // 해당 size에 맞는 idx를 받아오고
      bin = bin_at (av, idx); 
 
      if ((victim = last (bin)) != bin) // victim에 bin에 맞는 chunk를 받아옵니다.
        {
          if (victim == 0/* 받아온 chunk 0 이라면 malloc_consollidate를 호출합니다. */
            malloc_consolidate (av);
          else  // 그 외에는
            {
              bck = victim->bk;  // bck에 chunk의 bk 포인터를 저장합니다.
                 if (__glibc_unlikely (bck->fd != victim)) 
              // bck의 fd 즉, a - b로 linked 되어있을때 a 의 fd와 b의 bk가 변조되어있는지 확인합니다.
                {
                  errstr = "malloc(): smallbin double linked list corrupted";
                  goto errout;
                } // 변조되었다면 double linked list corrupted를 출력해줍니다.
 
              set_inuse_bit_at_offset (victim, nb); // 해당 victim chunk의 inuse bit를 설정해줍니다.
              bin->bk = bck; 
              bck->fd = bin;
              /* 해당 chubk를 제외하고 나머지 chunk들을 linked 해줍니다. */
 
              if (av != &main_arena) // 해당 chunk의 위치가 main_arena가 아니라면
                victim->size |= NON_MAIN_ARENA; 
                // 해당 chunkㅔ non main arena flag값을 설정해줍니다.
 
              check_malloced_chunk (av, victim, nb);
 
              void *= chunk2mem (victim);
              alloc_perturb (p, bytes);
              return p;
              // 마찬가지로 chunk + header 로 포인터를 ㅏㄷ아오고 alloc_perturb호출후 포인터를 반환해줍니다.
            }
        }
    }

small bin에서 사용 가능한 bin을 확인합니다.

 

1
2
3
4
5
6
  else // large bin 범위에 있을 때
    {
      idx = largebin_index (nb); // large bin 의 idx를 받아오고
      if (have_fastchunks (av)) // 현제 해당 arena에 fast size chunk가있는지 체크하고
        malloc_consolidate (av); // 있다면 malloc__consolidate를 해줍니다. ( chunk 병합 )
    }

large bin에서 사용 가능한 bin을 확인합니다.

 

 
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
  for (;; )
    {
      int iters = 0;
      while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
      // victim에 unsorted chunk를 받아오고
        {
          bck = victim->bk;
          // victim의 bk 포인터를 bck에 저장합니다.
          
          /* size_sz는 size_t의 size of값 입니다. 
               size_t 는 unsigned int type 입니다.
             
               2 * SIZE_SZ = 16 bytes, 최소 사이즈
               av -> system_mem 은 최대 사이즈를 뜻합니다(arena의 heap size) */
          if (__builtin_expect (victim->size <= 2 * SIZE_SZ, 0)
              || __builtin_expect (victim->size > av->system_mem, 0))
            malloc_printerr (check_action, "malloc(): memory corruption",
                             chunk2mem (victim), av);
          // 최소사이즈보다 작거나 같거나, 최대사이즈보다 크다면 memory corruption오류를 띄웁니다.
          
          size = chunksize (victim);
          // 해당 chunk의 size를 받아돕니다.
 
          if (in_smallbin_range (nb) && // small chunk 사이즈이며
              bck == unsorted_chunks (av) && // unsorted bin에 있는 유일한 chunk이며 
              victim == av->last_remainder && // 해당 chunk가 아레나의 last remainder이며
              (unsigned long) (size> (unsigned long) (nb + MINSIZE))
              // 해당 chunk의 크기가 요청된 크기보다 크다면
            {
              /* split and reattach remainder */
              remainder_size = size - nb;
              remainder = chunk_at_offset (victim, nb);
              unsorted_chunks (av)->bk = unsorted_chunks (av)->fd = remainder;
              av->last_remainder = remainder;
              remainder->bk = remainder->fd = unsorted_chunks (av);
              // remainder chunk와 할당 받을 수 있는 chunk를 계산하는 로직입니다.
              
              if (!in_smallbin_range (remainder_size))
                { // remainder size가 small bin 범위가 아니라면
                  remainder->fd_nextsize = NULL;
                  remainder->bk_nextsize = NULL;
                  // reminader chunk의 bk, fd next size를 NULL로 설정해줍니다.
                }
 
              set_head (victim, nb | PREV_INUSE |
                        (av != &main_arena ? NON_MAIN_ARENA : 0));
              set_head (remainder, remainder_size | PREV_INUSE);
              set_foot (remainder, remainder_size);
              
              // chunk의 header 값과 flag bit의 값을 설정 해 줍니다.
 
              check_malloced_chunk (av, victim, nb);
              void *= chunk2mem (victim);
              alloc_perturb (p, bytes);
              return p;
              // header 값을 포함한 chunk생성후 alloc_perturb를 호출하고 
              // 해당 chunk의 pointer을 반환합니다.
            }
 
          unsorted_chunks (av)->bk = bck;
          bck->fd = unsorted_chunks (av);
          
          /* 만약 위의 조건이 아니라면
              1.  small chunk size
            2.  unsorted bin의 유일한 chunk
            3. 해당 chunk가 아레나의 last reaminder이며
            4. 해당 chunk의 크기가 요청된 크기보다 크다면
            
            unsorted bin에서 제거합니다.
           */
          
          if (size == nb)
             // 요청된 크기와 chunk의 크기가 일치한다면 (정확히) 
            {
              set_inuse_bit_at_offset (victim, size);
              // 해당 chunk의 inuse bit를 설정해줍니다.
              if (av != &main_arena)
                victim->size |= NON_MAIN_ARENA;
              // 해당 arena가 main_arena가 아니라면
              // 해당 chunk의 NON_MAIN_ARENA bit를 설정해줍니다.
              
              check_malloced_chunk (av, victim, nb);
              void *= chunk2mem (victim);
              alloc_perturb (p, bytes);
              return p;
              
              // 바로 반환 과정을 거쳐줍니다. (반복 과정이므로 생략)
            }
 
          if (in_smallbin_range (size))
            { // size가 small bin 범위에 있다면
              victim_index = smallbin_index (size);
              bck = bin_at (av, victim_index);
              fwd = bck->fd;
              // size에 맞는 small bin의 idx를 받아오고
              // 해당하는 bin도 받아와서 bck에 넣어줍니다.
              // bck의 fd값은 fwd에 넣어줍니다.
            }
          else
            { // size가 large bin 범위에 있다면
              victim_index = largebin_index (size);
              bck = bin_at (av, victim_index);
              fwd = bck->fd;
              // size에 맞는 large bin의 idx를 받아오고
              // 해당하는 bin을 받아와서 bck에 넣어줍니다.
              // bck의 fd값은 fwd에 넣어줍니다.
 
              /* large bin 정렬 */
              if (fwd != bck) // large bin의 2개 이상에 chunk가 있다면.
                {     
                  size |= PREV_INUSE; // prev_inuse flag를 설정합니다.
                  
                  assert ((bck->bk->size & NON_MAIN_ARENA) == 0);
                  // NON_MAIN_NARENA 플래그를 assert의 인자로 넣어줍니다.
                  
                  if ((unsigned long) (size< (unsigned long) (bck->bk->size))
                    { // bin에 들어있는 chunk가 요청된 size의 크기보다 크다면
                      fwd = bck;
                      bck = bck->bk;
                      // fwd 와 bck를 설정해줍니다.    
                      
                      victim->fd_nextsize = fwd->fd;
                      victim->bk_nextsize = fwd->fd->bk_nextsize;
                      fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim;
                      // victim chunk의 fd, bk_nextsize도 설정해줍니다.
                      
                    }
                  else
                    { // bin에 들어있는 chunk가 요청된 size의 크기보다 작다면
                      assert ((fwd->size & NON_MAIN_ARENA) == 0);
                      // NON_MAIN_ARENA 플래그를 assert의 인자로 넣어줍니다.
                      
                      while ((unsigned longsize < fwd->size)
                        {
                          fwd = fwd->fd_nextsize;
                          assert ((fwd->size & NON_MAIN_ARENA) == 0);
                        } 
                      /* 
                      fwd의 size가 request size 크다면 
                      fwd 의 fd_nextsize를 fwd로 넣고
                      fwd의 size와 NON_MAIN_AERNA를 and 연산을 해줍니다.
                      */
 
                      if ((unsigned longsize == (unsigned long) fwd->size)
                        // 연산을 하고난뒤 fwd의 size와 request size가 같다면
                        fwd = fwd->fd;
                      else
                        {
                          victim->fd_nextsize = fwd;
                          victim->bk_nextsize = fwd->bk_nextsize;
                          fwd->bk_nextsize = victim;
                          victim->bk_nextsize->fd_nextsize = victim;
                          // fd, bk_nextsize를 설정해줍니다.
                        }
                      bck = fwd->bk;
                    }
                }
              else
                // large bin에 chunk가 한개뿐이라면
                victim->fd_nextsize = victim->bk_nextsize = victim;
                // fd, bk nextsize가 본인을 가르키도록 한다.
            }
 
          mark_bin (av, victim_index);
          victim->bk = bck;
          victim->fd = fwd;
          fwd->bk = victim;
          bck->fd = victim;
          // bin과 fd, bk를 linked 해줍니다.
 
        #define MAX_ITERS       10000
          if (++iters >= MAX_ITERS)
            break// 방금까지의 루틴을 최대 10000까지 실행해준다.
        }

unsorted bin을 찾아보고 적정한 크기의 chunk가 있다면 반환해줍니다.

 

 

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
      if (!in_smallbin_range (nb))
        { // large bin 범위에 있다면
          
          bin = bin_at (av, idx); // idx에 맞는 bin을 받아온다. 
          
          /* 비어있거나 chunk가 너무 작다면 스킵합니다. */
          if ((victim = first (bin)) != bin &&
              (unsigned long) (victim->size>= (unsigned long) (nb))
            {
              victim = victim->bk_nextsize;
              // victim에 victim의 bk_nextsize를 넣어줍니다.
              
              /* size에 chunksize를 넣어주고, size가  요청된 크기보다 작다면 */
              while (((unsigned long) (size = chunksize (victim)) <
                      (unsigned long) (nb))) 
                victim = victim->bk_nextsize;
              // victim에 victim의 bk_nextsize를 넣어줍니다.
            
 
              if (victim != last (bin) && victim->size == victim->fd->size)
                victim = victim->fd;
              // victim이 last bin이 아니며 victim의 사이즈가 victim의 fd의 size와 같다면
 
              remainder_size = size - nb;
              unlink (av, victim, bck, fwd);
              // size에서 request size를 빼주고 fd와 bk를 unlink해줍니다.    
              
            
              if (remainder_size < MINSIZE)
                {  // remainder size가 최소사이즈보다 작다면
                  set_inuse_bit_at_offset (victim, size);
                  if (av != &main_arena)
                    victim->size |= NON_MAIN_ARENA;
                  
                  // inuse flag와 NON_MAIN_ARENA flag를 설정해준다.
                }
              
              else
                { // 최소사이즈 이상으로 충분하다면
                  remainder = chunk_at_offset (victim, nb);
                  /* We cannot assume the unsorted list is empty and therefore
                     have to perform a complete insert here.  */
                  bck = unsorted_chunks (av);
                  fwd = bck->fd;
                  // bck와 fwd 설정
                  
                      if (__glibc_unlikely (fwd->bk != bck))
                    { // fd의 bk가 변조되었다면
                      errstr = "malloc(): corrupted unsorted chunks";
                      goto errout;
                    }
                  
                  remainder->bk = bck;
                  remainder->fd = fwd;
                  // remainder bk, fd를 bck, fwd로 설정
                  
                  bck->fd = remainder;
                  fwd->bk = remainder;
                  // bck의 fd와 fwd의 bk를 raminder로도 설정
                  // 간단한 unlink과정
                  
                  if (!in_smallbin_range (remainder_size))
                    { // 분할 하고 남은 remainder가 largebin 범위라면
                      remainder->fd_nextsize = NULL;
                      remainder->bk_nextsize = NULL;
                      // fd, bk_nextsize 초기화
                    }
                  set_head (victim, nb | PREV_INUSE |
                            (av != &main_arena ? NON_MAIN_ARENA : 0));
                  set_head (remainder, remainder_size | PREV_INUSE);
                  set_foot (remainder, remainder_size);
                  // flag값들 설정
                }
              check_malloced_chunk (av, victim, nb);
              void *= chunk2mem (victim);
              alloc_perturb (p, bytes);
              return p;
              // 반환과정
            }
        }
 
 

large bin 에 적당한 chunk가 있다면 반환해줍니다.

 

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
      ++idx;
      bin = bin_at (av, idx);
      block = idx2block (idx);
      map = av->binmap[block];
      bit = idx2bit (idx);
      
      for (;; )
        { /* 어려우므로 패스! */
          if (bit > map || bit == 0)
            {
              do
                {
                  if (++block >= BINMAPSIZE) /* out of bins */
                    goto use_top;
                }
              while ((map = av->binmap[block]) == 0);
 
              bin = bin_at (av, (block << BINMAPSHIFT));
              bit = 1;
            }
 
          /* Advance to bin with set bit. There must be one. */
          while ((bit & map) == 0)
            {
              bin = next_bin (bin);
              bit <<= 1;
              assert (bit != 0);
            }
 
          /* Inspect the bin. It is likely to be non-empty */
          victim = last (bin);
 
          /*  If a false alarm (empty bin), clear the bit. */
          if (victim == bin)
            {
              av->binmap[block] = map &= ~bit; /* Write through */
              bin = next_bin (bin);
              bit <<= 1;
            }
 
          else
            {
              size = chunksize (victim); // chunk size를 받아오고
 
              assert ((unsigned long) (size>= (unsigned long) (nb));
              // size가 request size보다 작다면 오류
              
              remainder_size = size - nb;
              // remainder size는 분할하고 남은 크기
              
              /* unlink */
              unlink (av, victim, bck, fwd); // unlink해주고
 
              /* Exhaust */
              if (remainder_size < MINSIZE)
                {
                  // 분할하고 남은크기가 최소 사이즈보다 작다면
                  
                  set_inuse_bit_at_offset (victim, size);
                  if (av != &main_arena)
                    victim->size |= NON_MAIN_ARENA;
                  // inuse bit flag를 설정해주고, NON_MAIN_ARENA판별후 flag 설정해준다.
                }
 
              /* Split */
              else
                { // remainder size가 충분하다면 
                  remainder = chunk_at_offset (victim, nb);
                  
                  /* We cannot assume the unsorted list is empty and therefore
                     have to perform a complete insert here.  */
                  bck = unsorted_chunks (av);
                  fwd = bck->fd;
                  // bk, fd 설정해주고
                  
                  if (__glibc_unlikely (fwd->bk != bck))
                     // fd의 bk가 의도치 않게 변조됬다면
                    {
                      errstr = "malloc(): corrupted unsorted chunks 2";
                      goto errout;
                    }
                  remainder->bk = bck;
                  remainder->fd = fwd;
                  bck->fd = remainder;
                  fwd->bk = remainder;
                  // remainder와 fd bk의 간단한 unlink
                  
 
                  /* advertise as last remainder */
                  if (in_smallbin_range (nb))
                    av->last_remainder = remainder;
                  // request size가 small bin 범위라면 
                  // arena의 last_reaminder chunk를 현재 remainder 로 설정
                  
                  if (!in_smallbin_range (remainder_size))
                    {
                      // request size가 large bin 범위라면
                      remainder->fd_nextsize = NULL;
                      remainder->bk_nextsize = NULL;
                      // fd, bk newxtsize값 초기화
                    }
                  set_head (victim, nb | PREV_INUSE |
                            (av != &main_arena ? NON_MAIN_ARENA : 0));
                  set_head (remainder, remainder_size | PREV_INUSE);
                  set_foot (remainder, remainder_size);
                  // flag값들을 설정해주고
                }
              check_malloced_chunk (av, victim, nb);
              void *= chunk2mem (victim);
              alloc_perturb (p, bytes);
              return p;
              // 반환과정을 거쳐준다
            }
        }

binmap 을 이용해서 확장된 bin list에서 사용가능한 chunk들을 확인해봅니다.

 

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
    use_top:
      /*
         If large enough, split off the chunk bordering the end of memory
         (held in av->top). Note that this is in accord with the best-fit
         search rule.  In effect, av->top is treated as larger (and thus
         less well fitting) than any other available chunk since it can
         be extended to be as large as necessary (up to system
         limitations).
         We require that av->top always exists (i.e., has size >=
         MINSIZE) after initialization, so if it would otherwise be
         exhausted by current request, it is replenished. (The main
         reason for ensuring it exists is that we may need MINSIZE space
         to put in fenceposts in sysmalloc.)
       */
 
      victim = av->top;
      size = chunksize (victim);
      // 아레나의 top을 victim에 넣고
      // top chunk의 size도 구한다.
      
      if ((unsigned long) (size>= (unsigned long) (nb + MINSIZE))
        { // 만약 size가 request size + header size보다 크거나 같다면
          remainder_size = size - nb;
          remainder = chunk_at_offset (victim, nb);
          av->top = remainder;
          // 분할해주고
          
          set_head (victim, nb | PREV_INUSE |
                    (av != &main_arena ? NON_MAIN_ARENA : 0));
          set_head (remainder, remainder_size | PREV_INUSE);
          // flag값들을 설정해주고
          
          check_malloced_chunk (av, victim, nb);
          void *= chunk2mem (victim);
          alloc_perturb (p, bytes);
          return p;
          // 해당 chunk를 반환해준다.
        }
 
      /* When we are using atomic ops to free fast chunks we can get
         here for all block sizes.  */
      else if (have_fastchunks (av))
        { // 만약 fastchunk가 있다면
          malloc_consolidate (av); // 병합을 해주고
          if (in_smallbin_range (nb))
            idx = smallbin_index (nb); 
          // request size가 smallbin 범위라면 small bin idx를 구해주고
          else
            idx = largebin_index (nb);
          // request size가 largebin 범위라면 large bin idx를 구해준다.
        }
 
      else
        { // 아니라면 sysmalloc으로 새로운 아레나를 만들어준다.
          void *= sysmalloc (nb, av);
          if (p != NULL)
            alloc_perturb (p, bytes);
          return p;
        }
    }

모든 조건이 어긋나서 할당받지 못했다면 top chunk에서 분할해서 할당해줍니다.

 

후 하

쓴다고 열심히 썻는데 지난번 문서로 작성했을 때보다 더 오류가 많은거같다..

다른 문서들도 읽어봐야겠다.

힘들다.

졸리다.

오래걸렸다.

 

끝!

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2024/03   »
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
31
글 보관함