故事背景:

  自己手动手写的一个lua外部库luaopen_xxx,采用了tolua++1.0.93,编译后得到xxx.dll,当在luajit中require 'xxx'后是正常的,但如果运行环境换成lua5.1.4,进程崩溃,调试后发现,出问题的现场在这个函数:

/*
** generic allocation routine.
*/
void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
global_State *g = G(L);
lua_assert((osize == ) == (block == NULL));
block = (*g->frealloc)(g->ud, block, osize, nsize);//就挂在这行了,内存问题
if (block == NULL && nsize > )
luaD_throw(L, LUA_ERRMEM);
lua_assert((nsize == ) == (block == NULL));
g->totalbytes = (g->totalbytes - osize) + nsize;
return block;
}

堆栈如下:

如果解决这个问题:

  先思考一下,free的时候崩溃,那就是内存问题,常见的有这么几种情况

  • 内存重复释放
  • 释放空指针
  • 释放非堆区内存
  • 虽然是堆区的内存,但由于bug导致偏移计算错误
  • 指针未初始化导致不该释放的野指针释放问题

接下来采用排除法,尝试注释掉所有的自己的代码,启动直接执行tolua环境初始化的函数,tolua_open(tolua_S);

进程直接崩溃,进一步二分排队法,发现执行到这几行代码会出问题

果然跟tolua++有关 ,那我们尝试不使用tolua++,单独执行这几行代码吧,照样崩溃。

这是一个空表,记得哪里看到过,luaC扩展库经常出现版本问题是因为,lua的所有空表其实都是指向同一个全局实例,由于版本不一样,导致这个全局变量的内存地址不一样

那应该就是空表地址不一致造成的了,那我们加一下打印吧,在lua.exe 和xxx.dll各自去打印一下空表地址即可

在ltable.c:73行增加打返回空表地址

#define dummynode        (&dummynode_)

static /*const*/ Node dummynode_ = {
{{NULL}, LUA_TNIL}, /* value */
{{{NULL}, LUA_TNIL, NULL}} /* key */
}; void *Get_dummynode() { return dummynode; }

在lua.c及xxx.c(动态库位置增加打钱)

extern void *Get_dummynode();

printf("%p\n", Get_dummynode());

执行结果,果然内存址不一样,所以会执行下面这段代码:

好了,问题水落石出了,怎么避免这个问题呢?

  • 避免使用空表吧,
  • 或者知道问题就好使用luajit就不会有这个问题了
  • 当然还可以避免使用tolua++

吐槽一下lua实现对这个全局变量的依赖及C的全局变量内存空间的不一致。当然想想,lua最初的设计是作为嵌入式语言,如果直接把整块编译进同一个模块也不会有这个问题

lua垃圾回收之空表的更多相关文章

  1. lua垃圾回收机制

    一.检测lua内存泄漏: 注:使用“collectgarbage("collect")”,局部变量v被回收,my_list没有被回收. 注:局部变量v占用的内存被回收. 注:将my ...

  2. 关于lua垃圾回收是否会执行__gc函数呢?

    直接上代码 -- test.lua do local x = setmetatable({},{ __gc = function() print("works") end }) e ...

  3. [Lua]内存泄漏与垃圾回收

    参考链接: http://colen.iteye.com/blog/578146 一.内存泄漏的检测 Lua的垃圾回收是自动进行的,但是我们可以collectgarbage方法进行手动回收.colle ...

  4. Java的垃圾回收和内存分配策略

    本文是<深入理解Java虚拟机 JVM高级特性与最佳实践>的读书笔记 在介绍Java的垃圾回收方法之前,我们先来了解一下Java虚拟机在执行Java程序的过程中把它管理的内存划分为若干个不 ...

  5. PHP新的垃圾回收机制:Zend GC详解

    概述 在5.2及更早版本的PHP中,没有专门的垃圾回收器GC(Garbage Collection),引擎在判断一个变量空间是否能够被释放的时候是依据这个变量的zval的refcount的值,如果re ...

  6. 【JVM】JVM系列之垃圾回收(二)

    一.为什么需要垃圾回收 如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断的分配内存空间而不进行回收.除非内存无限大,我们可以任性的分配而不回收,但是事实并非如此.所以,垃圾回收是必须的. 二. ...

  7. 【转】深入理解 Java 垃圾回收机制

    深入理解 Java 垃圾回收机制   一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再 ...

  8. java面试问题整理-垃圾回收

    对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址.大小以及使用情况.通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象,通过这种方式确定哪些对象是"可达的" ...

  9. 【C#进阶系列】21 托管堆和垃圾回收

    托管堆基础 一般创建一个对象就是通过调用IL指令newobj分配内存,然后初始化内存,也就是实例构造器时做这个事. 然后在使用完对象后,摧毁资源的状态以进行清理,然后由垃圾回收器来释放内存. 托管堆除 ...

随机推荐

  1. WPF中设置Border的BorderThickness属性会让背景图片产生模糊感

    <!--设置BorderThickness会让border的Background图片看起来有模糊感--> <Border x:Name="border" Bord ...

  2. 认识HDFS分布式文件系统

    1.设计基础目标 (1) 错误是常态,需要使用数据冗余  (2)流式数据访问.数据批量读而不是随机速写,不支持OLTP,hadoop擅长数据分析而不是事物处理.  (3)文件采用一次性写多次读的模型, ...

  3. 13 Timer和TimerTask

    下面内容转载自:http://blog.csdn.net/xieyuooo/article/details/8607220 其实就Timer来讲就是一个调度器,而TimerTask呢只是一个实现了ru ...

  4. free 和 delete 把指针怎么了

    使用free或delete之后,只是把指针所指的内容给释放掉,但是指针并没有被干掉,还是指向原来位置(并不是执行NULL),此时指针指向的内容为垃圾,被称为“野指针”. 举例说明几个重要容易迷糊的特征 ...

  5. HTTPS的误解(二)

    大家好,我们接着HTTPS的误解(一)接着讲,经常有人会说更换或转移服务器时要购买新证书,服务器SSL证书价格很贵,易维信(EVTrust)给大家澄清了这些容易产生误解的地方,详细见下面文章. 误解四 ...

  6. CC2530串口工作

    前言 嘿嘿,我只是写给我自己的一篇博客,今天研究了一天的CC2530,感觉好累,虽然是已经落伍的技术了,但是我觉得不要小看它,还是能够学到点东西的,随着学习的深入,渐渐感觉有点突破的苗头了!哈哈 CC ...

  7. maven+tomcat热部署

    1.首先修改tomcat安装目录下的conf文件夹中的tomcat-user.xml文件 <role rolename="manager-gui"/> <role ...

  8. Timer控件

    Timer控件是定期引发事件的控件,时间间隔的长度由interval属性定义,其值以毫秒为单位吗,若启用了该组件,则每个事件间隔引发一个Tick事件,Timer组件的主要方法包括start和stop, ...

  9. nginx配置样例

    简单的nginx配置如下,包含了静态文件配置.websocket.socket.io的配置: user nobody; worker_processes 3; #master_process off; ...

  10. 停课+2week

    可真是,累啊. 本以为停课之后会轻松一点,结果天天好累的说... 今天开始得去锻炼锻炼了... 已经好几次突然一阵晕眩了qwq... 希望我还能挺得住吧,至少要挺到WC结束啊... 这次,可是关系到我 ...