使用 ffi 将 lua 字符串转换为 C 字符串时出现分段错误
Segmentation fault while using ffi to convert lua strings to C strings
我在将 Lua 字符串转换为 C 字符数组时遇到了一个奇怪的问题。
local str = "1234567890abcdef"
local ffi = require "ffi"
ffi.cdef[[
int printf(const char *fmt, ...);
]]
print(#str)
print(str)
local cstr = ffi.new("unsigned char[?]", #str, str)
运行这段代码得到:
[root@origin ~]# luajit test.lua
16
1234567890abcdef
Segmentation fault
我知道 ffi.new("unsigned char[?]", #str+1, str)
会解决这个问题,但我不知道为什么。
我觉得不是[=15=]
的问题,因为我发现了一些奇怪的地方
- 如果
str
不是16字节,则不会发生这种情况。
- 如果我删除了我没有使用过的
ffi.cdef
,就不会发生这种情况。
如果我把ffi.cdef
放在ffi.new
后面,就不会发生这种情况。
[root@origin ~]# luajit test.lua
17
1234567890abcdefg
// this is the result that I only append a 'g' to `str`.
我尝试使用默认编译器参数 Luajit 2.0.5 和 Luajit 2.1.0-beta3。
所以,有没有人知道这是怎么发生的,谢谢。
正是因为字符串大小为17,而数组只分配了16字节。 https://github.com/LuaJIT/LuaJIT/blob/0c0e7b168ea147866835954267c151ef789f64fb/src/lj_cconv.c#L582 是将字符串复制到结果数组的代码。正如你所看到的,如果目标是数组并且它的大小小于字符串长度,它会收缩字符串;但是您的类型是 VLA(可变长度数组),并且未指定 VLA 大小(实际上是 2**32-1
,比 17 大得多)。
"I don't get error if" 不是这里的论点——你踩踏了用于其他用途的内存。有时用 0 踩踏额外的字节并不是致命的(例如,由于对齐,这个字节没有被使用,或者恰好已经是 0)或者不会导致硬崩溃 - 它不会使其正确。
我在将 Lua 字符串转换为 C 字符数组时遇到了一个奇怪的问题。
local str = "1234567890abcdef"
local ffi = require "ffi"
ffi.cdef[[
int printf(const char *fmt, ...);
]]
print(#str)
print(str)
local cstr = ffi.new("unsigned char[?]", #str, str)
运行这段代码得到:
[root@origin ~]# luajit test.lua
16
1234567890abcdef
Segmentation fault
我知道 ffi.new("unsigned char[?]", #str+1, str)
会解决这个问题,但我不知道为什么。
我觉得不是[=15=]
的问题,因为我发现了一些奇怪的地方
- 如果
str
不是16字节,则不会发生这种情况。 - 如果我删除了我没有使用过的
ffi.cdef
,就不会发生这种情况。 如果我把
ffi.cdef
放在ffi.new
后面,就不会发生这种情况。[root@origin ~]# luajit test.lua 17 1234567890abcdefg // this is the result that I only append a 'g' to `str`.
我尝试使用默认编译器参数 Luajit 2.0.5 和 Luajit 2.1.0-beta3。
所以,有没有人知道这是怎么发生的,谢谢。
正是因为字符串大小为17,而数组只分配了16字节。 https://github.com/LuaJIT/LuaJIT/blob/0c0e7b168ea147866835954267c151ef789f64fb/src/lj_cconv.c#L582 是将字符串复制到结果数组的代码。正如你所看到的,如果目标是数组并且它的大小小于字符串长度,它会收缩字符串;但是您的类型是 VLA(可变长度数组),并且未指定 VLA 大小(实际上是 2**32-1
,比 17 大得多)。
"I don't get error if" 不是这里的论点——你踩踏了用于其他用途的内存。有时用 0 踩踏额外的字节并不是致命的(例如,由于对齐,这个字节没有被使用,或者恰好已经是 0)或者不会导致硬崩溃 - 它不会使其正确。