openresty采用ffi方式调用C函数内存管理问题

500 views
Skip to first unread message

人cc

unread,
Aug 31, 2015, 12:35:10 PM8/31/15
to openresty, Yichun Zhang
hi,春哥

如果openresty采用ffi方式调用C函数,这个C函数内malloc一块空间返回,malloc的空间属于luajit管理,还是由C函数管理?

是不是需要在lua里面另外调用一个destroy函数,把malloc的内存free掉?

DeJiang Zhu

unread,
Aug 31, 2015, 10:08:04 PM8/31/15
to open...@googlegroups.com
hi,

在 2015年9月1日 上午12:35,人cc <code...@gmail.com>写道:
hi,春哥 

如果openresty采用ffi方式调用C函数,这个C函数内malloc一块空间返回,malloc的空间属于luajit管理,还是由C函数管理?

这个是需要自己管理的,如果想让 lua 的 gc 来管理,可以用 lua_newuserdata 来申请一块内存
 
是不是需要在lua里面另外调用一个destroy函数,把malloc的内存free掉?

是的,如无必要还是不建议这样搞,管理成本略大
 

--
--
邮件来自列表“openresty”,专用于技术讨论!
订阅: 请发空白邮件到 openresty...@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+...@googlegroups.com
归档: http://groups.google.com/group/openresty
官网: http://openresty.org/
仓库: https://github.com/agentzh/ngx_openresty
教程: http://openresty.org/download/agentzh-nginx-tutorials-zhcn.html

Yichun Zhang (agentzh)

unread,
Aug 31, 2015, 10:52:24 PM8/31/15
to 人cc, openresty
Hello!

2015-09-01 0:35 GMT+08:00 人cc:
> 如果openresty采用ffi方式调用C函数,这个C函数内malloc一块空间返回,malloc的空间属于luajit管理,还是由C函数管理?
>

C 函数 malloc 永远是和 free 配对的,这一点不必怀疑。既然你是用 ffi.C.malloc 分配的空间,便不是使用
LuaJIT 自己的分配器,所以不可能由 LuaJIT 的 GC 来管理。值得注意的是,ffi.C.malloc 返回的指针本身对应的
cdata 对象还是由 LuaJIT GC 来管理。这里的结构是:

[cdata object for the C pointer] --> [memory block allocated by
C's malloc()]

前者由 LuaJIT GC 管理,后者则需要你自己管理。

当然了,你仍然可以通过 ffi.gc() 函数在这个 C 指针的 cdata 对象上面注册自己的析构函数(在这个析构函数内你再调用
ffi.C.free),这样 C 指针对应的 cdata 对象(注意不是 malloc 分配的内存块)被 GC
时,它也会自动调用你注册的析构函数来执行 C 级别的内存释放(即上图中的第二个内存块)。

另一方面,你使用 ffi.new() 分配的 cdata 对象指向的内存块是由 LuaJIT GC 自动管理的。此时的结构就是简单的

[cdata object for the memory block allocated by LuaJIT via ffi.new]

一般很大的这种内存块还是通过 ffi.C.malloc 来分配比较好,这样可以避免耗尽 LuaJIT GC 管理内存的上限(x86_64 上默认只有 1GB)。

> 是不是需要在lua里面另外调用一个destroy函数,把malloc的内存free掉?

见上。

Regards,
-agentzh

Yichun Zhang (agentzh)

unread,
Aug 31, 2015, 10:54:19 PM8/31/15
to openresty
Hello!

2015-09-01 10:08 GMT+08:00 DeJiang Zhu:
>
> 这个是需要自己管理的,如果想让 lua 的 gc 来管理,可以用 lua_newuserdata 来申请一块内存
>

呃,lua_newuserdata 是标准 Lua 的 C API,这种 API 是不能和 LuaJIT 的 FFI
混用的。这是因为前者会在 LuaJIT VM 中产生副作用,而后者则是无副作用的。这也是为什么后者可以被 JIT 编译而前者不能。

正确的解是使用 ffi.new() 或者类似的 FFI 自己的 API 函数。

Regards,
-agentzh

DeJiang Zhu

unread,
Aug 31, 2015, 11:18:23 PM8/31/15
to open...@googlegroups.com
Hello,春哥

抱歉,回答错了,又涨知识了 :)

Reply all
Reply to author
Forward
0 new messages