いま書いている C 言語のライブラリの副産物としてカスタムアロケータを公開。以下の特徴を持つ。
- malloc/calloc/free のみ
-
allocator_get_size
で現時点のヒープ使用量を計測できる-
g_allocator_table
をイテレートすると個々のメモリアドレスと確保したサイズを取得出来る
-
- 終了時に
allocator_get_size() > 0
であるかどうかでメモリリークが発生したかどうかを確認できる
使う時は klib にある khash.h を予め同じディレクトリにおいておく必要がある。
// Public Domain
#include "khash.h"
KHASH_MAP_INIT_INT64(allocator, void *)
static khash_t(allocator) *g_allocator_table;
static void *
allocator_malloc(size_t size)
{
int ret;
void *ptr = malloc(size);
if (ptr) {
khiter_t it = kh_put(allocator, g_allocator_table, ptr, &ret);
kh_value(g_allocator_table, it) = (void *) size;
}
return ptr;
}
static void *
allocator_calloc(size_t length, size_t size)
{
int ret;
void *ptr = calloc(length, size);
if (ptr) {
khiter_t it = kh_put(allocator, g_allocator_table, ptr, &ret);
kh_value(g_allocator_table, it) = (void *) (size * length);
}
return ptr;
}
static void
allocator_free(void *ptr)
{
if (ptr) {
khiter_t it = kh_get(allocator, g_allocator_table, ptr);
kh_del(allocator, g_allocator_table, it);
free(ptr);
}
}
static size_t
allocator_get_size()
{
khiter_t it, end;
size_t size = 0;
for (it = kh_begin(g_allocator_table), end = kh_end(g_allocator_table); it < end; it++) {
if (kh_exist(g_allocator_table, it)) {
size += (size_t) kh_value(g_allocator_table, it);
}
}
return size;
}
これを拡張して以下に対応できるとちょっと使い勝手がよくなるかもしれない。
- malloc/realloc/calloc の呼び出し回数の計測
- realloc の対応
- libunwind を使ったメモリリーク箇所の特定
後者を実装するくらいなら valgrind を使うか gcc/clang に含まれる LeakSanitizer を使うことを検討するべき。