本篇文章,主要探讨一下lua中的内存管理(涉及到的文件 lmem.c,lauxlib.c )。
lua内存管理:
众所周知,lua是用纯c写的,所以lua中的内存管理,也就是用c方式对内存的管理。
/*
** About the realloc function:
** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize);
** (`osize’ is the old size, `nsize’ is the new size)
**
** Lua ensures that (ptr == NULL) iff (osize == 0).
**
** * frealloc(ud, NULL, 0, x) creates a new block of size `x’
**
** * frealloc(ud, p, x, 0) frees the block `p’
** (in this specific case, frealloc must return NULL).
** particularly, frealloc(ud, NULL, 0, 0) does nothing
** (which is equivalent to free(NULL) in ANSI C)
**
** frealloc returns NULL if it cannot create or reallocate the area
** (any reallocation to an equal or smaller size cannot fail!)
*/
注释中写的比较清楚,使用 void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); 接口来释放分配内存,释放和分配在同一个函数中完成,也可以只释放,或只分配,也可即释放又分配。
— 源码:
/*
** generic allocation routine.
*/
void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
global_State *g = G(L);
block = (*g->frealloc)(g->ud, block, osize, nsize);
g->totalbytes = (g->totalbytes – osize) + nsize;
return block;
}
把源码中断言去掉,便于代码分析:
global_State *g = …,通过当前栈指针L获得全局栈指针g,栈指针,以及全局栈指针,将在后续的文章中说明;
block = (*g->frealloc)(),通过frealloc接口释放block指针指向大小为osize的内存,申请nsize大小的内存,且用block指针指向,这里把要释放的内存和新申请的内存共享一个指针;
g->totalbytes = …, 刷新全局内存计数;
return block, 返回指向新申请的内存的指针;
内存管理的其他宏定义,如:luaM_reallocv,luaM_freemem,luaM_free,luaM_malloc,luaM_new等等,只是把luaM_realloc_接口再次封装了一下,比较容易理解。
frealloc真面目
在上面的分析中,只知道用frealloc接口释放分配内存,下面让我们来一览它的真面目。
static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
(void)ud;
(void)osize;
if (nsize == 0) {
free(ptr);
return NULL;
}
else
return realloc(ptr, nsize);
}
这块代码很简洁,当nsize==0,表示只释放ptr指向的内存,反之,则realloc一下ptr指向的内存,free,realloc都是c提供的内存操作API。