擬似mallocを作ってみる
C言語でmallocは便利だけれども、開発で多くの人が関わっている場合、他人のメモリリークや不正なアドレスへのアクセスなどのあおりを受けてSegmentation Faultなんていうことが結構あるそうな。
mallocで獲得したいメモリサイズが毎回固定の場合は、動的にメモリ領域を獲得するよりも、固定で予め確保しておいた中から使えるものを渡した方がよい。
既にmalloc前提でコードを書いている場合などは、擬似的なmallocを作ってあたかも動的に獲得しているように見せかけることは可能だろうということで、ちょっと書いてみた。
以下の例では、5つまではfreeせずに獲得可能だが、それを超えるとエラーを吐くように設定してある。実際の開発においては、無理のない上限値を設定することが重要だろう。
#include <stdio.h> #define ARRAY_MAX 5 typedef struct _hoge_ { int hoge; } Hoge; typedef struct _cell_ { int in_use; Hoge item; } Cell; static Cell buffers[ARRAY_MAX]; static int index = 0; void* hoge_malloc(size_t size) { /* 構造体決めうちなので引数なんて無視 */ Hoge *ret; index = index % ARRAY_MAX; if (buffers[index].in_use > 0) { return NULL; } ret = &buffers[index].item; buffers[index].in_use = 1; index++; return (void*)ret; } int hoge_free(void* ptr) { int i; for (i=0; i<ARRAY_MAX; i++) { if (&buffers[i].item == ptr && buffers[i].in_use > 0) { fprintf(stdout, "i'm free!: %d\n", (int)ptr); buffers[i].in_use = 0; return 0; } } fprintf(stderr, "this pointer is not in use: %d\n", (int)ptr); return -1; } #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; }
実行結果
$ ./nisemalloc allocated: 134518884 allocated: 134518892 allocated: 134518900 allocated: 134518908 allocated: 134518916 malloc error: 5 i'm free!: 134518884 i'm free!: 134518892 i'm free!: 134518900 i'm free!: 134518908 i'm free!: 134518916