malloc() の内部実装はかなり複雑にできてます。
「ちょこっとデバッグしたよーー \(o)/」
とか言うのは簡単なんですが、特定のビンがいつ使われたかシミュレーションしたいとかやってる人(自分含む)見ると、草はえますね…(笑えるの意味です…)もしくは毛が抜けそう…
(´・ω・`)
言葉が適当かどうかは分かりませんがダイナミックな動きをするので、特定の状況を再現しようとするのは極めて難しいです。
(´;ω;`)
でも筆者が試す限り動作したシミュレーションの結果をご報告するぐらいならできます…
main.cpp.
1 #include <stdlib.h> 2 #include <stdio.h> 3 4 typedef struct node_ { 5 void* data; 6 } node; 7 8 node* allocate() { 9 return malloc(sizeof(node)); 10 } 11 12 node* allocate8() { 13 return malloc(sizeof(node)*8); 14 } 15 16 node* allocate256() { 17 return malloc(sizeof(node)*256); 18 } 19 20 void bp() {} 21 22 int main() { 23 node *nodep[4096]; 24 node *node8p[4096]; 25 node *node256p[4096]; 26 int i; 27 28 for(i = 0; i < 4096; i++){ 29 nodep[i] = allocate(); 30 node8p[i] = allocate8(); 31 node256p[i] = allocate256(); 32 } 33 34 for(i = 0; i < 200000; i++) { 35 int index = i % 4096; 36 free(nodep[index]); 37 free(node8p[index]); 38 free(node256p[index]); 39 nodep[index] = allocate(); 40 node8p[index] = allocate8(); 41 node256p[index] = allocate256(); 42 } 43 44 for(i = 0; i < 4096; i++){ 45 free(nodep[i]); 46 free(node8p[i]); 47 free(node256p[i]); 48 } 49 50 bp(); 51 52 return 0; 53 }
このプログラムは malloc() と free() を何万回も繰り返すだけなんですがファーストビンと未整理ビン( Unsorted Bin )にフリーチャンクを入れてきます。
$ gcc main.c -g (gdb) break bp Breakpoint 1 at 0x709: file main.c, line 20. (gdb) run Starting program: Breakpoint 1, bp () at main.c:20 20 void bp() {} (gdb) p (&main_arena)->fastbinsY[0] $1 = (mfastbinptr) 0x555555fd59d0 (gdb) p (&main_arena)->fastbinsY[1] $2 = (mfastbinptr) 0x0 (gdb) p (&main_arena)->fastbinsY[2] $3 = (mfastbinptr) 0x0 (gdb) p (&main_arena)->fastbinsY[3] $4 = (mfastbinptr) 0x555555fd59f0 (gdb) p (&main_arena)->fastbinsY[3]->fd $5 = (struct malloc_chunk *) 0x555555fd5170 (gdb) p (&main_arena)->fastbinsY[3]->fd->fd $6 = (struct malloc_chunk *) 0x555555fd48f0 (gdb) p (&main_arena)->fastbinsY[3]->fd->fd->bk $7 = (struct malloc_chunk *) 0x0 (gdb) p (&main_arena)->fastbinsY[3]->fd->fd->mchunk_size $8 = 81 (gdb) p (&main_arena)->bins[0] $9 = (mchunkptr) 0x555555fd51c0 (gdb) p (&main_arena)->bins[0]->mchunk_size $10 = 2065 (gdb) p *(&main_arena)->bins[0] $11 = {mchunk_prev_size = 0, mchunk_size = 2065, fd = 0x555555fd4940, bk = 0x7ffff7bcaca0 <main_arena+96>, fd_nextsize = 0x0, bk_nextsize = 0x0} (gdb) p *(&main_arena)->bins[0]->fd $12 = {mchunk_prev_size = 0, mchunk_size = 2065, fd = 0x555555fd40c0, bk = 0x555555fd51c0, fd_nextsize = 0x0, bk_nextsize = 0x0} (gdb) p *(&main_arena)->bins[0]->fd->fd $13 = {mchunk_prev_size = 0, mchunk_size = 2065, fd = 0x555555fd3840, bk = 0x555555fd4940, fd_nextsize = 0x0, bk_nextsize = 0x0} (gdb) p (&main_arena)->bins[0]->fd->bk $15 = (struct malloc_chunk *) 0x555555fd51c0
まあ特に何か重要な行があるというわけじゃないですが、情報をまとめておきます。
アドレスもヒープ領域にありますし malloc() のシミュレーションとして悪くない結果です。
読者も色々とやってみるのは良いですが、時間は有限ですので、気をつけてくださいね。
Copyright 2018-2019, by Masaki Komatsu