46.1. チャンクを取り扱えるマクロ

チャンクをビンから削除するための unlink() みたいなマクロだけでなく、チャンクのリスト走査をしたり、属性情報を取得するためのマクロもあります。

以下の malloc.c のソース箇所は、チャンクに関するマクロを網羅しています。

malloc.c(https://github.com/MacKomatsu/glibc/blob/release/2.27/master/malloc/malloc.c). 

1245 /* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */
1246 #define PREV_INUSE 0x1
1247
1248 /* extract inuse bit of previous chunk */
1249 #define prev_inuse(p)       ((p)->mchunk_size & PREV_INUSE)
1250
1251
1252 /* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */
1253 #define IS_MMAPPED 0x2
1254
1255 /* check for mmap()'ed chunk */
1256 #define chunk_is_mmapped(p) ((p)->mchunk_size & IS_MMAPPED)
1257
1258
1259 /* size field is or'ed with NON_MAIN_ARENA if the chunk was obtained
1260    from a non-main arena.  This is only set immediately before handing
1261    the chunk to the user, if necessary.  */
1262 #define NON_MAIN_ARENA 0x4
1263
1264 /* Check for chunk from main arena.  */
1265 #define chunk_main_arena(p) (((p)->mchunk_size & NON_MAIN_ARENA) == 0)
1266
1267 /* Mark a chunk as not being on the main arena.  */
1268 #define set_non_main_arena(p) ((p)->mchunk_size |= NON_MAIN_ARENA)
1269
1270
1271 /*
1272    Bits to mask off when extracting size
1273
1274    Note: IS_MMAPPED is intentionally not masked off from size field in
1275    macros for which mmapped chunks should never be seen. This should
1276    cause helpful core dumps to occur if it is tried by accident by
1277    people extending or adapting this malloc.
1278  */
1279 #define SIZE_BITS (PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
1280
1281 /* Get size, ignoring use bits */
1282 #define chunksize(p) (chunksize_nomask (p) & ~(SIZE_BITS))
1283
1284 /* Like chunksize, but do not mask SIZE_BITS.  */
1285 #define chunksize_nomask(p)         ((p)->mchunk_size)
1286
1287 /* Ptr to next physical malloc_chunk. */
1288 #define next_chunk(p) ((mchunkptr) (((char *) (p)) + chunksize (p)))
1289
1290 /* Size of the chunk below P.  Only valid if prev_inuse (P).  */
1291 #define prev_size(p) ((p)->mchunk_prev_size)
1292
1293 /* Set the size of the chunk below P.  Only valid if prev_inuse (P).  */
1294 #define set_prev_size(p, sz) ((p)->mchunk_prev_size = (sz))
1295
1296 /* Ptr to previous physical malloc_chunk.  Only valid if prev_inuse (P).  */
1297 #define prev_chunk(p) ((mchunkptr) (((char *) (p)) - prev_size (p)))
1298
1299 /* Treat space at ptr + offset as a chunk */
1300 #define chunk_at_offset(p, s)  ((mchunkptr) (((char *) (p)) + (s)))
1301
1302 /* extract p's inuse bit */
1303 #define inuse(p)                    \
1304   ((((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size) & PREV_INUSE)
1305
1306 /* set/clear chunk as being inuse without otherwise disturbing */
1307 #define set_inuse(p)                    \
1308   ((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size |= PREV_INUSE
1309
1310 #define clear_inuse(p)                    \
1311   ((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size &= ~(PREV_INUSE)
1312
1313
1314 /* check/set/clear inuse bits in known places */
1315 #define inuse_bit_at_offset(p, s)               \
1316   (((mchunkptr) (((char *) (p)) + (s)))->mchunk_size & PREV_INUSE)
1317
1318 #define set_inuse_bit_at_offset(p, s)               \
1319   (((mchunkptr) (((char *) (p)) + (s)))->mchunk_size |= PREV_INUSE)
1320
1321 #define clear_inuse_bit_at_offset(p, s)               \
1322   (((mchunkptr) (((char *) (p)) + (s)))->mchunk_size &= ~(PREV_INUSE))
1323
1324
1325 /* Set size at head, without disturbing its use bit */
1326 #define set_head_size(p, s)  ((p)->mchunk_size = (((p)->mchunk_size & SIZE_BITS) | (s)))
1327
1328 /* Set size/use field */
1329 #define set_head(p, s)       ((p)->mchunk_size = (s))
1330
1331 /* Set size at footer (only when chunk is not in use) */
1332 #define set_foot(p, s)       (((mchunkptr) ((char *) (p) + (s)))->mchunk_prev_size = (s))

この中で重要なのは set_head() と set_foot() マクロです。

チャンクのヘッダーとフッターを設定しています。

チャンクのヘッダーとは use ビットやサイズ「 mchunk_size 」のことでして、このヘッダーから次のチャンクのアドレスを割り出すことができます。

1328 /* Set size/use field */
1329 #define set_head(p, s)       ((p)->mchunk_size = (s))

フッターはフリーチャンクで前のチャンクのサイズのことです。

1331 /* Set size at footer (only when chunk is not in use) */
1332 #define set_foot(p, s)       (((mchunkptr) ((char *) (p) + (s)))->mchunk_prev_size = (s))

フッター「 mchunk_prev_size 」を設定することでチャンクが使われていない事が判別できます。

Copyright 2018-2019, by Masaki Komatsu