Lua在构建VM
的时候是要求传入内存管理函数的!
/*
** Type for memory-allocation functions
*/
typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud)
说明: 需要在
nsize
为0的时候提供释放。ud
则是可以告知这是在哪个堆上的! 当ptr
传入null
时,osize
的含义变成了对象的类型
一般而言,我们都不是直接使用lua_newstate
去直接创建vm
,而是使用
LUALIB_API lua_State *luaL_newstate (void) {
lua_State *L = lua_newstate(l_alloc, NULL);
if (l_likely(L)) {
lua_atpanic(L, &panic);
lua_setwarnf(L, warnfoff, L); /* default is warnings off */
}
return L;
}
static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
(void)ud; (void)osize; /* not used */
if (nsize == 0) {
free(ptr);
return NULL;
}
else
return realloc(ptr, nsize);
}
Lua还有一组宏来管理不同类型的内存,但是最终都是找到global_state->frealloc
来申请内存,global_state->frealloc
就是在创建lua_newstate
的时候传入的内存管理函数
lmem.h
在这些宏中,有一个比较值得注意的函数
void *luaM_growaux_ (lua_State *L, void *block, int nelems, int *psize,
int size_elems, int limit, const char *what) {
void *newblock;
int size = *psize;
if (nelems + 1 <= size) /* does one extra element still fit? */
return block; /* nothing to be done */
if (size >= limit / 2) { /* cannot double it? */
if (l_unlikely(size >= limit)) /* cannot grow even a little? */
luaG_runerror(L, "too many %s (limit is %d)", what, limit);
size = limit; /* still have at least one free place */
}
else {
size *= 2;
if (size < MINSIZEARRAY)
size = MINSIZEARRAY; /* minimum size */
}
lua_assert(nelems + 1 <= size && size <= limit);
/* 'limit' ensures that multiplication will not overflow */
newblock = luaM_saferealloc_(L, block, cast_sizet(*psize) * size_elems,
cast_sizet(size) * size_elems);
*psize = size; /* update only when everything else is OK */
return newblock;
}
它是用来管理可变长数组的。其主要策略是当数组空 间不够时,扩大为原来的两倍。
PREVIOUSLua的全局状态机