擬似malloc続き
擬似mallocを作ってみるの続きです。
リングバッファの要領で(というかまんまリングバッファ)、ついつい入れてしまったmallocをあとから置き換えるためのmallocモドキを改良(?)してみました。
もちろんこんなのがmallocの完全な置き換えにはなるはずもないですが、
- 取り出すデータのサイズ(構造体)は常に同じ
- データは、確保された順に開放される
ってこれまんまキューじゃないですか、ただのFIFOじゃないですか、という突っ込みは置いといて。
やってることは、固定サイズの構造体の配列を一定数予め確保して連結リストにしておき、読み出しポインタと戻しポインタがおっかけっこする感じ。この方法だと、同時に確保できるデータは、配列要素数-1個となる。(そういや排他制御もきっちりやらないといけない)
コード
#include <stdio.h> #define ARRAY_MAX 5 typedef struct _hoge_ { /* 逐次取り出したいデータの構造体 */ int hoge; } Hoge; typedef struct _cell_ { /* データを格納するための連結リストのセル */ Hoge item; struct _cell_ *next; } Cell; static Cell buffers[ARRAY_MAX]; static Cell *mallocp = &buffers[0]; /* 取り出すときに進めるポインタ */ static Cell *freep = &buffers[0]; /* 戻すときに進めるポインタ */ static int init = 0; void hoge_init() { int i; for (i=0; i<ARRAY_MAX; i++) { buffers[i].next = &buffers[(i+1)%ARRAY_MAX]; } } void* hoge_malloc(size_t size) { /* 構造体決めうちなので引数なんて無視 */ Cell *ret; if (init == 0) { /* 最初だけ初期化 */ hoge_init(); init = 1; } if (mallocp->next == freep) { /* これ以上ポインタを進められない */ return NULL; } ret = mallocp; mallocp = mallocp->next; return (void*)ret; } void hoge_free(void* ptr) { if (ptr != mallocp) { /* mallocpに追いつかなければ一つ進める */ printf("i'm free!: %d\n", (int)freep); freep = freep->next; } return; } #define HOGE_MAX 10 int main(int argc, char* argv[]) { int i; Hoge *hoges[HOGE_MAX]; for (i=0; i<HOGE_MAX; i++) {/* 初期化 */ hoges[i] = NULL; } i = 0; while (1) { hoges[i] = (Hoge*)hoge_malloc(sizeof(Hoge)); if (hoges[i] == NULL) { fprintf(stdout, "malloc error: %d\n", i); break; } fprintf(stdout, "allocated: %d\n", (int)hoges[i]); i++; } for (i=0; i<HOGE_MAX && hoges[i]!=NULL; i++) { hoge_free(hoges[i]); } return 0; }
実行結果
$ ./nisemalloc2 allocated: 134518752 allocated: 134518760 allocated: 134518768 allocated: 134518776 malloc error: 4 i'm free!: 134518752 i'm free!: 134518760 i'm free!: 134518768 i'm free!: 134518776
結論
最初からmalloc使わないで済むような実装を考えよう。