Lua処理系コード読み(6) luaM_realloc_

lmem.c

/*
** generic allocation routine.
*/
void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
  global_State *g = G(L);
  lua_assert((osize == 0) == (block == NULL));
  block = (*g->frealloc)(g->ud, block, osize, nsize);
  if (block == NULL && nsize > 0)
    luaD_throw(L, LUA_ERRMEM);
  lua_assert((nsize == 0) == (block == NULL));
  g->totalbytes = (g->totalbytes - osize) + nsize;
  return block;
}

allocとfreeはこの関数経由で行う。

man realloc

書式
void *realloc(void *ptr, size_t size);
説明
realloc() は、ポインタ ptr が示すメモリブロックのサイズを変更して size バイトにする。新旧 のサイズのうち、小さいほうのブロックに含まれる内容は変更されない。新しく割り当てられたメモ リ の 内容は初期化されない。 size がどの値であっても、 ptr が NULL の場合には malloc(size) と等価である。 size が 0 で ptr が NULL でない場合には、 free(ptr) と等価である。 ptr が NULL 以外の場合、 ptr は以前に呼び出された malloc(), calloc(), realloc() のいずれかが返し た値でなければならない。 ptr が指す領域が移動されていた場合は free(ptr) が実行される。
返り値
realloc() は新たに割り当てられたメモリへのポインタを返す。これはあらゆる種類の変数に対応で き るようにアラインメントされており、 ptr とは異なることもある。割り当て要求に失敗した場合 は NULL が返る。 size が 0 の場合には、NULL もしくは free() に渡すことができるポインタが返 る 。 realloc() が失敗した場合には、元のブロックは変更されない。つまり、解放されたり移動さ れたりはしない。

問題ないというのはわかるんだけど何故なのかよく知らない。一つのところだけ通すから

  g->totalbytes = (g->totalbytes - osize) + nsize;

みたいな処理が一箇所で済んで楽って話とかかな。

lmem.h

#define luaM_reallocv(L,b,on,n,e) \
  ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ?  /* +1 to avoid warnings */ \
    luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \
    luaM_toobig(L))

#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0)
#define luaM_free(L, b)   luaM_realloc_(L, (b), sizeof(*(b)), 0)
#define luaM_freearray(L, b, n, t)   luaM_reallocv(L, (b), n, 0, sizeof(t))

#define luaM_malloc(L,t)  luaM_realloc_(L, NULL, 0, (t))
#define luaM_new(L,t)   cast(t *, luaM_malloc(L, sizeof(t)))
#define luaM_newvector(L,n,t) \
    cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t)))

#define luaM_reallocvector(L, v,oldn,n,t) \
   ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t))))

マクロなどでmalloc、freeなどを定義。

test