lua虚拟机内存申请与释放

首先看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后再分配一次,如果还是失败则抛出异常。

你可能感兴趣的:(虚拟机,内存,lua)