lua虚拟机内存申请与释放

来源:互联网 发布:网络彩票2016最新消息 编辑:程序博客网 时间:2024/06/07 18:31

首先看lua虚拟机的创建函数

LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud)

参数lua_Alloc f便是lua虚拟机的内存管理函数,虚拟机需要的内存创建回收都是通过这个函数实现。

这个函数的原型是:

typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);

其中的ud就是创建lua虚拟机时的第二个参数

我们一般不使用lua_newstate直接创建虚拟机,而是使用一个辅助函数

LUALIB_API lua_State *luaL_newstate (void) {  lua_State *L = lua_newstate(l_alloc, NULL);  if (L) lua_atpanic(L, &panic);  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);}

这个缺省实现的功能是:
1.如果nsize是0则实现内存释放功能
2.重新调整指针所指向内存空间的大小,可以扩展也可以收缩

lua虚拟机在操作内存时,并没有直接使用这个函数,而是对其进行了一系列包装:

luaM_reallocv   ->      luaM_realloc_   ->      l_alloc luaM_freemem    ->      luaM_realloc_   ->      l_alloc luaM_free       ->      luaM_realloc_   ->      l_alloc luaM_freearray  ->      luaM_realloc_   ->      l_alloc luaM_malloc ->      luaM_realloc_   ->      l_alloc luaM_new    ->      luaM_malloc ->      luaM_realloc_   ->      l_alloc luaM_newvector  ->      luaM_reallocv   ->      luaM_realloc_   ->      l_alloc luaM_newobject  ->      luaM_realloc_   ->      l_alloc luaM_growvector ->      luaM_growaux_   ->      luaM_reallocv   ->  luaM_realloc_   ->      l_alloc 

这些函数最终都会使用luaM_realloc_ 进行内存分配

void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {  void *newblock;  global_State *g = G(L);  size_t realosize = (block) ? osize : 0;  lua_assert((realosize == 0) == (block == NULL));#if defined(HARDMEMTESTS)  if (nsize > realosize && g->gcrunning)    luaC_fullgc(L, 1);  /* force a GC whenever possible */#endif  newblock = (*g->frealloc)(g->ud, block, osize, nsize);  if (newblock == NULL && nsize > 0) {    lua_assert(nsize > realosize);  /* cannot fail when shrinking a block */    if (g->version) {  /* is state fully built? */      luaC_fullgc(L, 1);  /* try to free some memory... */      newblock = (*g->frealloc)(g->ud, block, osize, nsize);  /* try again */    }    if (newblock == NULL)      luaD_throw(L, LUA_ERRMEM);  }  lua_assert((nsize == 0) == (newblock == NULL));  g->GCdebt = (g->GCdebt + nsize) - realosize;  return newblock;}

这段代码的大致意思就是使用l_alloc 进行内存分配,如果分配失败则进行一次完全gc后再分配一次,如果还是失败则抛出异常。

0 0
原创粉丝点击