同个staitc变量不同的内存地址 --- 不稳定的singleton模式

LUA 的gc管理释放时有这么一句:

void luaH_free (lua_State *L, Table *t) {
  if (t->node != dummynode)
    luaM_freearray(L, t->node, sizenode(t), Node);
  luaM_freearray(L, t->array, t->sizearray, TValue);
  luaM_free(L, t);
}

其中 t->node != dummynode 是对该节点是否应该被释放的一句判断,而dummynode 是一个static 的单件实例的地址 定义如下

#define dummynode (&dummynode_)
static const Node dummynode_ = {
  {{NULL}, LUA_TNIL},  /* value */
  {{{NULL}, LUA_TNIL, NULL}}  /* key */
};

容易看出作者的意图是想用dummynode 作为非法的节点值用,因为该节点常用来做是非判断,为了区别C这边的指针没用传统的非法指针值NULL( PS一句,还好没写成NULL,要不这么做会让这种问题藏得更深)其实这种模式按effect里建议的可以用个static 的接口定义取代 个类似 if(!g_Instance) g_Instance =new Node;  用来方便控制g_Instance的产生时机。但这个也并没有解决接下来要出现的问题。

程序每次一旦运行到LUA尝试进行gc管理的时候就崩溃,原因是free了一个不属于new出来的内存。这块内存就是这个dummynode。 放断点看在新节点赋值的时候

  t->node = cast(Node *, dummynode);

这时候的dummynode也确实就是释放时t->node所保持的值,但释放的那句

 if (t->node != dummynode)

奇怪的是为啥dummynode != dummynode呢,这同一个变量居然被分配到2个不同的地址上了!!

这问题细想也不奇怪,原因就出在对LUA .lib 的引入上。这是工程里用到LUA的一个结构:


其中UI_DLL 引入了LUA_LIB ,并封装了部分操作 ,而 GAME_EXE 也引入了 LUA_LIB 。估计有人会问为啥EXE还需要引入LUA_LIB ,在使用 UI_DLL 时不已经会加载UI_LIB这时候就把LUA_LIB也继承包含了吗。 正常是这样,但由于GAME_EXE用到了由模板实现的注册接口,而这块接口由于没法被UI_DLL 所调用到而并没在UI_LIB中被包含,要想GAME_EXE成功link通过,还得把LUA_LIB引入才行。 

问题由此产生:在UI_DLL包含的LUA_LIB 在代码里已经产生出了一个dummynode,而GAME_EXE包含的LUA_LIB在不同的链接处又产生出了一个dummynode。而在运行的时候正好生成的时候调用的GAME_EXE里链接的那段,释放的时候又回到了UI_DLL里的那段了。

解决这个问题的方案有2个,一个是把UI_DLL 变成 UI_LIB ,这样在编译 UI_LIB 的时候就不会需要依赖 LUA_LIB ,而只是在GAME_EXE里才需要依赖 这个库。 另外一个方案就是把注册这个模板实现从LUA_LIB 里剥出来,这样一来让GAME_EXE不用再依赖 LUA_LIB 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值