使用 ffi 将 lua 字符串转换为 C 字符串时出现分段错误



我在将Lua字符串转换为C char arry时遇到了一个奇怪的问题。

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)会解决这个问题,但我不知道为什么。

我不认为这是问题,因为我发现了一些奇怪的点。

  • 如果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 大得多)。

"如果我不会出错"在这里不是一个论点 - 你踩踏用于其他事情的内存。有时用 0 踩踏额外的字节并不是致命的(例如,由于对齐,这个字节无论如何都没有使用,或者只是碰巧已经是 0)或不会导致硬崩溃 - 它不会使其正确。

最新更新