[tolua++]tolua++中暴露对象给lua时,一定要把析构函数暴露给lua

题目不知道怎么取才好,但是意思很简单:

如果你暴露一个复杂对象给Lua,实现类似于OO编程的话,那么也要把析构函数暴露给Lua.

否则的话,lua gc的时候,回收垃圾对象,没有找到回收函数,就直接free掉了,这在C++中,是相当致命的.

tolua++中的tolua_cclass函数,用来注册lua对象,

TOLUA_API void tolua_cclass (lua_State* L, const char* lname, const char* name, const char* base, lua_CFunction col)

同时会把最后的那个参数col,注册到lua对象的元表里面:

static void push_collector(lua_State* L, const char* type, lua_CFunction col) {

    /* push collector function, but only if it‘s not NULL, or if there‘s no

       collector already */

    if (!col) return;

    luaL_getmetatable(L,type);

    lua_pushstring(L,".collector");

        //....

    lua_pushcfunction(L,col);

        //....

而发生gc的时候,class_gc_event函数会去在lua对象的元表里面找".collector"这个key,如果没找到,就用default的析构,否则就用用户提供的析构函数:

top = lua_gettop(L);

if (tolua_fast_isa(L,top,top-1, lua_upvalueindex(2))) /* make sure we collect correct type */

{

    /*fprintf(stderr, "Found type!\n");*/

    /* get gc function */

    lua_pushliteral(L,".collector");

    lua_rawget(L,-2);           /* stack: gc umt mt collector */

    if (lua_isfunction(L,-1)) {

        /*fprintf(stderr, "Found .collector!\n");*/

    }

    else {

        lua_pop(L,1);

        /*fprintf(stderr, "Using default cleanup\n");*/

        lua_pushcfunction(L,<strong>tolua_default_collect</strong>);//这个是默认的析构函数

    }

    lua_pushvalue(L,1);         /* stack: gc umt mt collector u */

    lua_call(L,1,0);

而默认的析构函数是C free的简单封装:

TOLUA_API int tolua_default_collect (lua_State* tolua_S)

{

 void* self = tolua_tousertype(tolua_S,1,0);

 free(self);

 return 0;

}

如果你通过tolua++注册一个复杂类型给lua的话,析构函数不被调用,而直接调用了free,会发生很多未定义行为.

这就是在我们服务器中隐藏了超过两年的一个Bug......

时间: 2024-11-04 19:51:43

[tolua++]tolua++中暴露对象给lua时,一定要把析构函数暴露给lua的相关文章

Win32下 Qt与Lua交互使用(三):在Lua脚本中connect Qt 对象

话接上文.笔者为了方便使用Lua,自己编写了一个Lua的类.主要代码如下: QLua.h 1 #ifndef QLUA_H 2 #define QLUA_H 3 4 // own 5 #include "include/lua.hpp" 6 7 // qt 8 #include <QObject> 9 #include <QFile> 10 #include <QDebug> 11 12 #include <QWidget> 13 #in

python列表中添加对象时的注意

最近在用python写代码,用到了对象数组.在c++中我们要使用能够灵活操作的对象数组,一般会用stl的vector类,该类的push_back方法可以将一个对象的拷贝加入到vector对象中,所以当使用[]下标对vector的元素进行修改时,原来的作为push_back参数的那个对象的值并不会改变.python中类似的方法是列表的append方法,但是要注意此时若加入到列表中的是基础数据类型,则是值传递,若是对象,则是引用传递.这种参数的传递方式和java一样.因此,在python中通过列表下

对象中含有java.util.Date时使用JSONArray.fromObject时时间显示问题

这两天做项目的时候,需要在action中把一个对象转换成JSONArray,我使用的是JSONArray.fromObject.可是,别的String类型的数据在页面端已经拿到了,就是Date类型的有问题.用firebug看的,日期打出来的完全就不是自己想要的(本来想把year.month.day拼接起来显示).后来,网上找了好些资料,终于找到了一个方法.action中代码如下: JsonConfig jsonConfig = new JsonConfig(); jsonConfig.regis

Win32下 Qt与Lua交互使用(二):在Lua脚本中使用Qt类

话接上篇.成功配置好Qt+Lua+toLua后,我们可以实现在Lua脚本中使用各个Qt的类.直接看代码吧. #include "include/lua.hpp" #include <QWidget> #include <QApplication> #include <QFile> #include <QDebug> static int tolua_new_QWidget(lua_State* pState) { QWidget* wid

ARPG客户端中场景对象体系设计

一.场景对象体系 二.场景对象生命周期管理 场景对象的生命周期,不适合采用原始的c++管理方式, 即由使用者自己负责删除.而应该采用引用计数方式, 自动负责删除. 采用引用计数方式, 目前用法比较广的分两类: 1.智能指针, 如boost::shared_ptr, 这种方式原理是基于c++对象的生命周期和析构函数来实现的, 而且引用计数是由智能指针对象保存的.在这种方式下, 对象的传递和引用都是使用智能指针对象, 例如: class A; typedef boost::shared_ptr<A>

无法为数据库中的对象分配空间,因为&#39;PRIMARY&#39;文件组已满

用SQL Server2012,做数据保存时出错,错误信息:无法为数据库'***'中的对象'***'分配空间,因为'PRIMARY'文件组已满.请删除不需要的文件.删除文件组中的对象.将其他文件添加到文件组或为文件组中的现有文件启用自动增长,以便增加可用磁盘空间. 解决办法:打开SQL Server Management Studio,右键报错的数据库,选择"属性",弹出对话框,选择"文件"页签,查看是否限制了数据库文件增长,若没有做限制,再查看磁盘剩余空间是否足够

深入分析面向对象中的对象概念(转)

OOP:面向对象编程,一提到面向对象,大家可能就想到类,接口.一说特性,大家可能张口就来:继承.封装.多态,那么到底什么样的对象(类)才是真正意义上的对象呢?特别是现在流行的DDD领域驱动设计思想,讲究职责划分,那么如何定义一个对象(类)它应该具有的一些特性.行为方法及承担责任成为关键. 一个看似简单的问题,其实也是耐人思索,之前也在网上看到一些人关于讨论类的设计问题,认为设计类时不应该考虑数据库,我觉得这只是实现真正的面向对象设计的基础,也是前提条件,大多数程序员之前都是受面向过程编程思想的影

ASP.NET中Server对象

1.asp.net中常见对象: Request:服务器读取浏览器请求中的信息. Response:将服务器中的信息发送给浏览器. Server:获取请求服务器的相关信息. Application:应用程序级对象,多用户之间可以共享数据. Session:会话,用户通过网址访问服务器时会话启动. 下面的图可以简单理解为:我们发布的服务器为Server对象,在服务器上运行的web程序为Application对象,每个客户端对web程序的一个访问就是一个Session 2.Global.aspx 初始

hibernate中持久化对象的生命周期(三态:自由态,持久态,游离态 之间的转换)

三态的基本概念: 1,  暂时状态(Transient):也叫自由态,仅仅存在于内存中,而在数据库中没有对应数据.用new创建的对象,它没有持久化,没有处于Session中,处于此状态的对象叫暂时对象: 2,  持久化状态(Persistent):与session关联而且在数据库中有对应数据.已经持久化,添?到了Session缓存中.如通过hibernate语句保存的对象.处于此状态的对象叫持久对象: 3,  游离状态(Detached):持久化对象脱离了Session的对象.如Session缓