[07] C言語の独自メモリアロケータの振り返り ... ソースコード全文

|本シリーズのトップページ|
|:--|
|https://qiita.com/robozushi10/items/ca7c25dab3c279ba4e2b|

# はじめに

本記事の趣旨は「[01 概要](https://qiita.com/drafts/be9e965ac06ca1af798b/edit)」に記しているが、
要は 13年前(=2008年) に K&R をマネて実装した「自作メモリアロケータ」の振り返りである.

本項ではコード全文を記す.　

## 余談

### 1.

<font color="gray">デバッグ用関数定義 memman_debug.c を見ると、「hoge」「piyo」といったログ表示をさせていた..</font>
<font color="gray">当時、ifdef が切り替わることをテストしていたのだろうか..</font>

### 2. 

<font color="gray">不必要にラッパ関数が多いが、当時の開発現場のコードをマネたのだと思う.</font>
<font color="gray">当時のコードは printf() を呼び出すまでに、5個ほどラッパ関数が存在していた.</font>

　

## Makefile

```bash

PROGRAM=memman

SRCS=main.c \
     memman.c \
     memman_core.c \
     memman_resource.c \
     memman_debug.c 
     

HDRS=memman.h \
     priv_memman_core.h \
     priv_memman_debug.h \
     priv_memman_std.h
    
OBJS=$(SRCS:%.c=%.o)

CC = gcc
LIBPATH = 
LIBS     = -lpthread
CFLAGS = -Wall -g -O0 $(INCHEADER) 
LDFLAGS = $(LIBPATH)

$(PROGRAM):$(SRCS) $(HDRS)
	$(CC) $(CFLAGS) -o $(PROGRAM) $(SRCS) $(LDFLAGS) $(LIBS)

clean:
	\rm -f $(PROGRAM) $(OBJS)
```

　


## main.c

```c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <unistd.h>


#include "memman.h"
#ifdef DEBUG
#include "priv_memman_debug.h"
#endif
#ifdef DEBUG_CHK_MEMLEAK
#include "priv_memman_debug.h"
#endif

sem_t  Sem;

int
main()
{
    mem_inst_t     * instance = NULL;
    char           * buf[1000];
    int              i        = 0;
    int              j        = 0;
    req_mem_inst_t   req;

    /* セマフォについても管理モジュールを作成し，内部で資源情報を
     * 保持すると良いが，ここでは作成していない  */
    sem_init /* セマフォの初期化 */
    (
        &Sem, /* セマフォ変数の初期化 */
        0,    /* 0：スレッドでセマフォ共有, 非0：プロセスで共有 */
        1     /* 並列処理数 */
    );

    req.functor_alloc = &malloc,
    req.functor_free  = &free,
    req.pool_size     = 4096,
    req.key           = "main",
    req.sem           = &Sem;
    req.pshared       = 0;
    req.value         = 0;

#if 1
    instance = Mman_new_inst(&req);
    for(j = 0; j < 500; j++)
    {
        for(i = 0; i < 1000; i++)
        {
            buf[i] = instance->alloc(0,i);
        }

        for(i = 0; i < 1000; i++) /* alloc よりも小さい値にするとメモリリークが確認出来る */
        {
            instance->free(0, buf[i]);
        }
    }

#ifdef DEBUG_CHK_MEMLEAK
    //Mmc_debug_dump_buf();
#endif /* DEBUG_CHK_MEMLEAK */

    /* robozushi10 セマフォ破棄についても管理モジュールを作成すると良い */
    Mman_delete_inst(instance->id);

    Mman_close();   /* フリーリスト破棄 + フリーノード破棄 */
#else
    for(j = 0; j < 500; j++)
    {
        for(i = 0; i < 1000; i++)
        {
            buf[i] = malloc(i);
        }

        for(i = 0; i < 1000; i++)
        {
            free(buf[i]);
        }
    }
#endif

    return 0;
}
```

　


## memman.c

```c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "memman.h"
#include "priv_memman_std.h"
#include "priv_memman_core.h"
#include "priv_memman_debug.h"

extern mman_t memrtbl[];

/* key からメモリリソース情報の ID を取得する */
static int
mman_key2id(const char * key)
{
    int       id         =  0;
    const int invalid_id = -1;

    for(id = 0; id < Mman_get_rsrc_num(); id++)
    {
        if(MMAN_STRCMP(key, ==, memrtbl[id].key))
        {
            return id;
        }
    }
    /* even if id is not exist, you don't need error message */
    return invalid_id;
}

/* メモリリソーステーブルに登録 */
static void
mman_register_memrtbl(req_mem_inst_t * req, mem_inst_t * inst)
{
    int id = mman_key2id(req->key);

    memrtbl[id].id            = id;
    strcpy(memrtbl[id].key, req->key);
    memrtbl[id].instance      = inst;
    memrtbl[id].functor_alloc = req->functor_alloc;
    memrtbl[id].functor_free  = req->functor_free; 
    memrtbl[id].pool_size     = req->pool_size;
    memrtbl[id].rest_size     = req->pool_size;
    memrtbl[id].position      = 0;
    memrtbl[id].sem           = req->sem;
}

/* ID からメモリリソース情報へのポインタ取得 */
inline
static mman_t *
mman_get_rsrc(int id)
{
    return &memrtbl[id];
}

/* key からメモリリソース情報へのポインタ取得 */
static mman_t *
mman_get_rsrc_by_key(char * key)
{
    int id = mman_key2id(key);
    if(-1 == id)
    {
        FATAL("mman_key2id error at mman_get_rsrc_by_key(%s)\n", key);
    }

    return &memrtbl[id];
}

/* インスタンスのセットアップ */
static mem_inst_t *
mman_create_instance(req_mem_inst_t * req)
{
    mman_t     * p    = NULL;
    mem_inst_t * inst = NULL;

    inst = malloc(sizeof(mem_inst_t));
    if(NULL == inst)
    {
        FATAL("malloc error at mman_create_instance\n");
    }

    /* メモリリソーステーブルに登録 */
    mman_register_memrtbl(req, inst);

    /* メモリリソース情報へのポインタ取得 */
    p                   = mman_get_rsrc_by_key(req->key);
    inst->id            = p->id;
    inst->alloc         = &Mman_alloc;
    inst->free          = &Mman_free;
    inst->get_used_size = NULL;
    inst->get_rest_size = NULL;

    return inst;
}

/* ID をキーにして，インスタンスを返す(内部用) */
inline
static mem_inst_t *
mman_get_inst(int id)
{
    if((id < 0) || (Mman_get_rsrc_num() < id))
    {
        err_mesg("invalid id(%d)\n", id);
    }
    return memrtbl[id].instance;
}

/* key をキーにして，インスタンスを返す(内部用) */
inline
static mem_inst_t *
mman_get_inst_by_key(char * key)
{
    int      id = mman_key2id(key);

    /* even if id is not exist, you don't need error message */
    return memrtbl[id].instance;
}

/* すでにインスタンスが存在しているかどうか */
static int
mman_is_inst_already_exist(char * key)
{
    mem_inst_t * p = NULL;
    enum { not_exist, exist };

    p = mman_get_inst_by_key(key);
    
    return (NULL != p) ? exist : not_exist;
}

/* インスタンス作成I/F */
mem_inst_t *
Mman_new_inst(req_mem_inst_t * req)
{
    mem_inst_t  * inst     = NULL;
    int           exist    = 0; 
    static  int   is_flist = 0;

    if(!is_flist)
    {
        Mmc_initialize(Mman_get_rsrc_num());
        is_flist = 1;
    }
    /* 既にインスタンスが存在しているか */
    exist = mman_is_inst_already_exist(req->key);
    if(exist)
    {
        err_mesg("instance is already exist\n");
        return NULL; /* すでにインスタンスが存在している */
    }

    /* インスタンス作成 */
    inst = mman_create_instance(req);
    if(NULL == inst)
    {
        err_mesg("could not create instance\n");
        return NULL;
    }

    return inst;
}

inline
static void
mman_erase_instance(mem_inst_t * inst)
{
    free(inst);
}

void
Mman_delete_inst(int id)
{
    mman_t     * p    = mman_get_rsrc(id);
    mem_inst_t * inst = p->instance;

    mman_erase_instance(inst);
    p->instance = NULL;
}

void
Mman_close(void)
{
    Mmc_shutdown(Mman_get_rsrc_num());
}

mem_inst_t *
Mman_get_inst(int id)
{
    return mman_get_inst(id);
}

void *
Mman_alloc(int id, size_t size)
{
    mman_t  * p = mman_get_rsrc(id);

    /* robozushi10: verify request size */

    return Mmc_alloc(id, size, p->functor_alloc);
}

void
Mman_free(int id, void * ptr) 
{
    mman_t  * p = mman_get_rsrc(id);

    Mmc_free(id, ptr, p->functor_free);
}
```

　


## memman.h

```bash

/* 外部公開ヘッダ */
#ifndef   __MEMMAN_H__
#define   __MEMMAN_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>

#if 0
#define  DEBUG                      /* デバッグログ表示                   */
#define  DEBUG_CHK_MEMLEAK          /* メモリリークチェック               */
#endif
#define  DBG_BUFSIZ        (128)    /* メモリリークチェック用バッファ行数 */

/* インスタンス要求時に用いる */
typedef
struct _req_mem_inst_t
{
    void         * (* functor_alloc)(size_t  size); /* メモリ獲得ファンクター */
    void           (* functor_free) (void  * ptr);  /* メモリ解放ファンクター */
    size_t         pool_size; /* メモリサイズ        */
    char         * key;       /* 識別キー(7文字まで) */
    sem_t        * sem;       /* セマフォID          */
    int            pshared;   /* 0: プロセスでセマフォを共有する */
    unsigned int   value;     /* 同時実行可能な数    */
}
    req_mem_inst_t;

/* ユーザが使用するアクセッサ */
typedef
struct _mem_inst_t
{
    void   * (* alloc)        (int id, size_t  size); /* メモリ獲得I/F */
    void     (* free)         (int id, void  * ptr);  /* メモリ解放I/F */
    void     (* get_used_size)(void);                 /* 使用量取得I/F */
    void     (* get_rest_size)(void);                 /* 残量取得関I/F */
    int      id;
}
    mem_inst_t;

/* インスタンス作成I/F */
mem_inst_t * Mman_new_inst   (req_mem_inst_t * req);
mem_inst_t * Mman_get_inst   (int id);
void         Mman_delete_inst(int id);

/* メモリ操作I/F */
void       * Mman_alloc(int id, size_t size);
void         Mman_free (int id, void * p) ;
void         Mman_close(void);

#endif /* __MEMMAN_H__ */
```

　


## memman_core.c

```c

/* [プログラミング言語C] p225 を流用 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "memman.h"
#include "priv_memman_std.h"
#include "priv_memman_core.h"
#ifdef DEBUG 
#include "priv_memman_debug.h" /* for debug */
#endif /* DEBUG */
#ifdef DEBUG_CHK_MEMLEAK
#include "priv_memman_debug.h" /* for debug */
#endif /* DEBUG */

#define    NALLOC      5120  /* x86 では，sbrk(NALLOC * 8) が最小単位になる */
                            /* 極端に小さくする(2など)とデバッグ出来る */
typedef
struct _mmc_flist_t
{
    Header   base;
    Header * freep;
}
    mmc_flist_t;

static mmc_flist_t ** flist_tbl = NULL;

static void        * mmc_alloc    (int id, unsigned   nbytes, void * functor);
static void          mmc_free     (int id, void     * p,      void * functor);
static void        * add_freelist (int id, void     * ap);
static Header      * morecore     (int id, unsigned   nu, void * functor);
inline
static mmc_flist_t * mmc_get_flist(int id);


/* フリーリストテーブルの構築 */
void
Mmc_initialize(int resource_num)
{
    int    i = 0;

    flist_tbl = malloc(sizeof(mmc_flist_t **) * resource_num);

    for(i = 0; i < resource_num; i++)
    {
        flist_tbl[i] = malloc(sizeof(mmc_flist_t));
    }
}


/* フリーノードをシステムに返却する */
static void
mmc_walk_flist_for_free(void)
{
    ;
}

/* フリーリストテーブルの破棄 */
void
Mmc_shutdown(int resource_num)
{
    int    i = 0;

    for(i = 0; i < resource_num; i++)
    {
        free(flist_tbl[i]);
    }
    free(flist_tbl);

    mmc_walk_flist_for_free(); /* フリーノードをシステムに返却する */
}

void
Mmc_free
(
    int    id,
    void * p,
    void * functor
)
{
    (void) id;
    mmc_free(id, p, functor);
}

/* メモリ解放関数。実際には free せずにフリーリストにつなぐだけ */
static void
mmc_free(int id, void * p, void * functor)
{
    Header * bp = (Header *)p;
    Header * hp = ((Header *)p)-1;

    (void) functor;
/* robozushi10: need sem look */
    MMAN_DBP("[id:%d]mmc_free(): mmc_free(%p)\n", id, p);

    hp->s.ptr = NULL;

#ifdef DEBUG_CHK_MEMLEAK
    Mmc_debug_rm_addr((unsigned)p);
#endif /* DEBUG_CHK_MEMLEAK */
    MMAN_DBP("[id:%d]mmc_free(): call add_freelist(%p)\n", id, bp);
    add_freelist(id, (void *)bp);
/* robozushi10: need sem unlook */
}


void *
Mmc_alloc
(
    int      id,
    size_t   size,
    void   * functor
)
{
    return mmc_alloc(id, size, functor);
}

static void *
mmc_alloc(int id, unsigned nbytes, void * functor)
{
    mmc_flist_t  * flist  = NULL;
    Header       * freep  = NULL;
    Header       * prevp  = NULL;
    Header       * base   = NULL;
    Header       * p      = NULL;
    unsigned int   nunits = ((nbytes + sizeof(Header)-1) / sizeof(Header)) + 1;

/* robozushi10: need sem look */
    flist  = mmc_get_flist(id);
    freep  = flist->freep;
    prevp  = freep;
    base   = &(flist->base);

    if(prevp == NULL) /* 初回のアロケートの場合 */
    {
        base->s.ptr = base;
        freep       = base;
        prevp       = base;
        base->s.size = 0;
    }
    /* ２回目以降は、前回 freep で記憶させておいたアドレスを辿ってフリーノードを探す */

    /* フリーリストを辿って使用可能なフリーノードを探す */
    MMAN_DBP("[id=%d]mmc_alloc(): mmc_alloc(%d bytes)\n", id, nbytes);
    for(p = prevp->s.ptr;  ; prevp=p, p=p->s.ptr)
    {
        MMAN_DBP
        (
            "[id:%d]mmc_alloc(): (p, p->s.ptr, p->s.size) = (%p, %p, %dblk)\n",
            id, p, p->s.ptr, p->s.size
        );
        /* 見つかったフリーノードには要求分以上のブロックがあるか？ */
        if(p->s.size >= nunits)
        {
            if(p->s.size == nunits) /* 丁度、要求分だけフリーノードがあった */
            {
                MMAN_DBP("[id:%d]mmc_alloc(): found free-node just fit size(%d blk)\n", id, p->s.size);
                /* フリーノードを全部使い切ったので，フリーリストから削除する */
                prevp->s.ptr = p->s.ptr;
            }
            else /* フリーノードから nunitsブロック分拝借する */
            {
                /* フリーノードの末尾から使用する */
                p->s.size -= nunits;
                p         += p->s.size;
                p->s.size = nunits;
                MMAN_DBP("[id:%d]mmc_alloc(): found free-node(%p, %dblk)\n", id, p, p->s.size);
            }
            /* p が現在ポイントしているよりも1つ前のフリーノードのアドレスを freep に *
             * 記憶させておく. これにより，次に mmc_alloc() が呼ばれたときは freep で記憶 *
             * させておいたフリーノードから探索を開始する                             *
             * (フリーリストは循環構造になっているので全てのノード探索は可能)         */
            flist->freep = freep = prevp;    
            MMAN_DBP("[id:%d]mmc_alloc(): Remember freep=prevp=%p\n", id, freep);
            MMAN_DBP("[id:%d]mmc_alloc(): return %p\n", id, (void *)(p+1));
#ifdef  DEBUG_CHK_MEMLEAK
            Mmc_debug_cp_addr((unsigned)(void *)(p+1));
#endif /* DEBUG_CHK_MEMLEAK */
/* robozushi10: need sem unlook */
            return (void *)(p+1); /* ヘッダ部分を除いた先頭領域のアドレスを返す */ 
        }

        /* 初期状態では p は base をポイントしている => base.s.ptr=freep=prevp=&base */
        if(p == freep)
        {   /* フリーリストを一周した */
            MMAN_DBP("[id:%d]mmc_alloc(): not found free-node\n", id);
            MMAN_DBP("[id:%d]mmc_alloc(): call morecore(%d blk)\n", id, nunits);
            flist->freep = freep;
#if 1
            p = morecore(id, nunits, functor); /* フリーノードが無いのでシステムにメモリ要求 */
#else
#endif
            if(p == NULL)
            {
/* robozushi10: need sem unlook */
                return NULL; /* メモリリーク!! 割り当て可能なメモリが無い */
            }
        }
    } /* for loop end */
/* robozushi10: need sem unlook */
}


/* システム依存のメモリ要求関数(void * functor)を呼び出す */
static Header *
morecore(int id, unsigned nu, void * functor)
{
    mmc_flist_t  * flist              = mmc_get_flist(id);
    Header       * freep              = flist->freep;
    char         * cp                 = NULL;
    Header       * up                 = NULL;
    void         * (* p_func)(size_t) = functor;

    /* 最低 NALLOC からブロックサイズを要求する */
    nu = (nu < NALLOC) ? NALLOC : nu;

    MMAN_DBP("[id:%d]morecore(): require %dblk,  %dByte\n", id, nu, nu * sizeof(Header));
#if 0  /* sbrk() を使った場合 */
    cp = (void *)sbrk(nu * sizeof(Header)); /* ヒープ領域を広げる */
    if(cp == (char *)-1)
    {
        return NULL;
    }
#else  /* malloc で動作確認済み */
    cp = (*p_func)(nu * sizeof(Header));
    if(cp == NULL)
    {
/* robozushi10: need sem unlook */
        FATAL
        (
            "[id:%d]morecore(): alloc(func=%p)(size=%d)\n",
            id,
            p_func,
            nu * sizeof(Header)
        );
    }
#endif

    up         = (Header *)cp; /* sbrk()の返り値 */
    up->s.size = nu;           /* 使用可能なブロックサイズ値 */
    MMAN_DBP("[id:%d]morecore(): allocated new node (addr=%p, blk size=%d)\n", id, up, up->s.size);
    MMAN_DBP("[id:%d]morecore(): call add_freelist(%p)\n", id, (void *)(up+1));
    freep =  add_freelist(id, (void *)(up+1)); /* ヘッダを除いたブロック領域の先頭アドレス */
    return freep;
}


static void *
add_freelist(int id, void * ap)
{
    mmc_flist_t  * flist  = mmc_get_flist(id);
    Header       * freep  = flist->freep;
    Header       * bp     = ((Header *)ap)-1;
    Header       * p      = NULL;

    /* ブレークポイントがフリーノード間に無ければループを継続 */
    for(p = freep; !((p < bp) && (bp < p->s.ptr)); p = p->s.ptr)
    {    
        if((p >= p->s.ptr) && (bp > p || bp < p->s.ptr))
        {
        /* リストを一周し，かつ，ブレークポイントがフリーノード間にある場合   */
        /* なお、if(p >= p->s.ptr) だけではフリーリストの終端が見つけられない */
#ifdef  DEBUG
            if(bp > p)
            {
                MMAN_DBP("[id:%d]add_freelist(): bp(%p) > p(%p)\n", id, bp, p);
            }
            else if(bp < p->s.ptr)
            {
                MMAN_DBP("[id:%d]add_freelist(): bp(%p) < p->s.ptr(%p)\n", id, bp, p->s.ptr);
            }
#endif
            break;
        }
    }

    if((bp + bp->s.size) == p->s.ptr)
    { /* 新たにノードを登録すると丁度既にあるノードと連結する場合，*
       * 2つのノードを合併させる                                   */
        MMAN_DBP
        (
            "[id:%d]add_freelist(): bp->s.size(%d) + p->s.ptr->s.size(%d) = %d\n",
            id,
            bp->s.size,
            p->s.ptr->s.size,
            bp->s.size + p->s.ptr->s.size
        );
        bp->s.size += p->s.ptr->s.size;
        bp->s.ptr   = p->s.ptr->s.ptr;    
    } 
    else
    {
        bp->s.ptr = p->s.ptr;
        MMAN_DBP("[id:%d]add_freelist(): link [new node(%p)] => [next node(%p)]\n", id, bp, bp->s.ptr);
    }

    if(p + p->s.size == bp)
    { /* 現在のフリーノードにブロック分(s.size)だけアドレスを進めると *
       * sbrk()で確保した領域の先頭アドレスと同じになる場合, 現在のフ *
       * リーリスト領域と bp 領域を併せてしまう                       */
        p->s.size += bp->s.size;    
        p->s.ptr   = bp->s.ptr;
    }
    else
    {
        p->s.ptr = bp;
        MMAN_DBP("[id:%d]add_freelist(): link(2) [new node(%p)]\n", id, p->s.ptr);
    }                
    flist->freep = freep = p;

    return freep;
}

/* フリーリスト情報構造体を返す */
inline
static mmc_flist_t *
mmc_get_flist(int id)
{
    return flist_tbl[id];
}
```

　


## memman_debug.c

```c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "memman.h"
#include "priv_memman_std.h"
#include "priv_memman_core.h"
#include "priv_memman_debug.h"

static unsigned buf[DBG_BUFSIZ];

void
Mmc_debug_cp_addr(unsigned addr)
{
    static int i = 0;
printf("hogepiyo\n");
    i &= (DBG_BUFSIZ - 1); /* DBG_BUFSIZ を超えると上書きする */
    buf[i++] = addr;
}

void
Mmc_debug_rm_addr(unsigned addr)
{
    int i = 0;

//printf("hogepiyo2\n");
    for(i = 0; i < DBG_BUFSIZ; i++)
    {
        if(buf[i] == addr)
        {
            buf[i] = 0;
        }
    }
}

void
Mmc_debug_dump_buf(void)
{
    fprintf(stderr, "-------------------------\n");
    fprintf(stderr, "   memory leack check    \n");
    fprintf(stderr, "-------------------------\n");

    int i = 0;

    while(i != DBG_BUFSIZ)
    {
        i &= (DBG_BUFSIZ - 1);
        if(buf[i] != 0)
        {
            printf("[%d] 0x%08x\n", i, buf[i]);
        }
        i++;
    }
}
```

　


## memman_resource.c

```c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
#include "memman.h"
#include "priv_memman_std.h"
#include "priv_memman_core.h"
#include "priv_memman_debug.h"

/* メモリリソーステーブル *//* 型の定義は priv_memman_std.h にて */
#define  MMAN_RESOURCE_BOTTOM   \
    {   -1,     "",    NULL,        0,        0,      NULL,        NULL,       NULL,          0,          0,      NULL}

mman_t
memrtbl[] =
{   
    /* [id]   [key] [sem_id] [pshared] [sem val] [instance] [alloc func] [free func] [pool size] [rest size] [position]*/
    {    0, "main",    NULL,        0,        0,      NULL,        NULL,       NULL,          0,          0,      NULL},
    MMAN_RESOURCE_BOTTOM
};

int
Mman_get_rsrc_num(void)
{
    return MMAN_KEYNUM(memrtbl);
}
```

　


## priv_memman_core.h

```bash

#ifndef   __PRIV_MEMMNAN_CORE_H__
#define   __PRIV_MEMMNAN_CORE_H__

#include "memman.h"
#include "priv_memman_std.h"

#define  ALIGNSIZE  4

typedef
struct header_t
{
    union    header * ptr;
    unsigned int      size;
}
    header;

union header
{
    header        s;
    unsigned char align[ALIGNSIZE];
};

typedef union header Header;

void * Mmc_alloc(int id, size_t   size, void * functor);
void   Mmc_free (int id, void   * p,    void * functor);
void   Mmc_initialize(int resource_num);
void   Mmc_shutdown  (int resource_num);
#endif /* __PRIV_MEMMNAN_CORE_H__ */
```

　


## priv_memman_debug.h

```bash

#ifndef   __PRIV_MEMMAN_DEBUG_H__
#define   __PRIV_MEMMAN_DEBUG_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "memman.h"
#include "priv_memman_std.h"
#include "priv_memman_core.h"

void Mmc_debug_cp_addr (unsigned addr);
void Mmc_debug_rm_addr (unsigned addr);
void Mmc_debug_dump_buf(void);

#endif /* __PRIV_MEMMAN_DEBUG_H__ */
```

　


## priv_memman_std.h

```bash

#ifndef   __PRIV_MEMMNAN_STD_H__
#define   __PRIV_MEMMNAN_STD_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "memman.h"

#define  MMAN_KEYNUM(a)          (sizeof(a)/sizeof(*a))
#define  MMAN_STRCMP(a, R, b)                                    \
(                                                                \
    (a) && (b) && (strlen(a) R strlen(b)) && (0 R strcmp(a, b))  \
)

#ifdef DEBUG
#define err_mesg(fmt, args...)               \
{                                            \
    fprintf                                  \
    (                                        \
        stderr,                              \
        "[%s:%-4d] ERROR: " fmt,             \
        __FILE__,                            \
        __LINE__,                            \
        ## args                              \
    );                                       \
}

#define FATAL(fmt, args...)                  \
{                                            \
    fprintf                                  \
    (                                        \
        stderr,                              \
        "[%s:%-4d] FATAL: " fmt,             \
        __FILE__,                            \
        __LINE__,                            \
        ## args                              \
    );                                       \
    exit(2);                                 \
}

#define MMAN_DBP(fmt, args...)               \
{                                            \
    fprintf                                  \
    (                                        \
        stdout,                              \
        "[%s:%-4d] DEBUG: " fmt,             \
        __FILE__,                            \
        __LINE__,                            \
        ## args                              \
    );                                       \
}
#else  /* DEBUG */
#define err_mesg(fmt, args...)               
#define FATAL(fmt, args...)                  
#define MMAN_DBP(fmt, args...)               
#endif /* DEBUG */

/* typedef を使った場合 */
typedef void * Fn_alloc(size_t size);
typedef void   Fn_free (void * ptr);

/* メモリ管理構造体 */
typedef
struct mman_t
{
    int             id;
    char            key[8];
    sem_t         * sem;
    int             pshared;
    unsigned  int   value;
    mem_inst_t    * instance;
#if 0  /* typedef を使った場合 */
    Fn_alloc      * alloc;
    Fn_free       * free;
#else
    void          * (* functor_alloc)(size_t   size);
    void            (* functor_free) (void   * ptr);
#endif
    size_t          pool_size;
    size_t          rest_size;
    void          * position;
}
    mman_t;

extern int Mman_get_rsrc_num(void);

#endif /* __PRIV_MEMMNAN_STD_H__ */
```