详解luaL_newstate()

windows 7平台 VS 2012 lua 5.3.3源码 debug模式下

上篇lua数据结构讲完了,这篇看lua执行过程中的数据变化
正好元旦放假,在家没什么事,可以坐下来安安静静看lua源码,开启VS,单步调试

extern "C"
{
    #include "lauxlib.h"  
    #include "lualib.h"  
    #include "lua.h"
}
void main()
{
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
    lua_close(L);
    return;
}

lua_State *L = luaL_newstate();看看这句代码到底发生了什么

LUALIB_API lua_State *luaL_newstate (void) {
  lua_State *L = lua_newstate(l_alloc, NULL);
  if (L) lua_atpanic(L, &panic);
  return L;
}

`/*
** thread state + extra space
*/
typedef struct LX {
  lu_byte extra_[LUA_EXTRASPACE];//这里默认为sizeof(void *)即为4
  lua_State l;
} LX;

/*
** Main thread combines a thread state and the global state
*/
typedef struct LG {
  LX l;
  global_State g;
} LG;

LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
  int i;

  lua_State *L;
  global_State *g;

  LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG)));
  if (l == NULL) return NULL;
  L = &l->l.l;
  g = &l->g;
 ...
  if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
    /* memory allocation error: free partial state */
    close_state(L);
    L = NULL;
  }
  return L;
}

观察到lua_newstate 接受2个参数,一个类型是lua_Alloc,另一个是void *

其中lua_Alloc是什么类型,我们跟踪看看

typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
定义了一个lua_Alloc的函数指针类型,其返回值为 void *

lua_newstate(l_alloc, NULL);

 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_newstate(l_alloc, NULL);中其实简单理解就是把l_alloc函数指针传递进去,方便在ua_newstaten内调用l_alloc函数

看看l_alloc这个函数干了啥,居然ud,osize 2个参数都没有使用,不知道为啥还留这么多参数,可能历史原因吧,这样安慰自己

nsize不为0时,就重新分配ptr指向的内存大小为nsize,为0就释放内存

继续看看 lua_newstate函数中luaD_rawrunprotected

 /* type of protected functions, to be ran by 'runprotected' */
typedef void (*Pfunc) (lua_State *L, void *ud);

int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud)

 if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
    /* memory allocation error: free partial state */
    close_state(L);
    L = NULL;
  }

luaD_rawrunprotected 中调用 f_luaopen 中调用 stack_init(L, L) 初始化L大小
这里不贴代码了,可以下载lua源码中查看

收获:

由于lua和C交互主要是栈,我们看和栈有关的地址L->top ,L->stack,L.stacksize

lua_newstate 内存分配,初始化lua_State ,global_State g

stack_init初始化栈大小,默认为2*LUA_MINSTACK,即 2* 20 = 40

L->top是指向栈实际使用的下一个地址的

L->stack地址为栈起始地址,并且小于L->top地址,平时我们看其它博文栈顶在上面,但是内存中其实是在高地址也就是下面.

/* extra stack space to handle TM calls and some other extras */
#define EXTRA_STACK 5

堆栈大小 L.stacksize = (L->stack_last - L->stack) /sizeof(lua_TValue) + EXTRA_STACK

目前堆栈已使用 (L->top- L->stack) /sizeof(lua_TValue)

lua_newtable(L); luaC_checkGC(L); luaC_step (lua_State *L)会导致GC,所以lua_openlibs后面栈的大小改变,这里GC暂不深入

数据结构中每个变量的含义还未完全了解,得好好把lua源码中的注释看一遍

不必深入了解这些数据在内存中的表示,什么内存对齐啥的,会增加学习负担,重点看数据之间的转移,数据流向

希望大家有好的相关文章可以留言推荐给我.

从图看L的结构
详解luaL_newstate()_第1张图片

参考资料:

结构体和联合体内存大小计算
http://blog.csdn.net/vincent_1011/article/details/4479965

函数指针用法
http://blog.csdn.net/qll125596718/article/details/6891881

你可能感兴趣的:(小菜鸟从C看lua)