【问题标题】:Segmentation fault while using ffi to convert lua strings to C strings使用 ffi 将 lua 字符串转换为 C 字符串时出现分段错误
【发布时间】:2017-11-02 10:55:59
【问题描述】:

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

我认为这不是\0 的问题,因为我发现了一些奇怪的地方。

  • 如果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。

那么,有谁知道这是怎么回事,谢谢。

【问题讨论】:

  • 这个问题是由于缺少终止零的地方。您必须使用#str+1
  • @EgorSkriptunoff 我不这么认为,你能解释一下为什么它只发生在转换 16 字节字符串时?

标签: lua ffi luajit


【解决方案1】:

这正是因为字符串大小为 17 但数组仅分配了 16 个字节。 https://github.com/LuaJIT/LuaJIT/blob/0c0e7b168ea147866835954267c151ef789f64fb/src/lj_cconv.c#L582 是将字符串复制到结果数组的代码。如您所见,如果目标是数组并且它的大小小于字符串长度,它会缩小字符串;但是您的类型是 VLA(可变长度数组),并且未指定 VLA 的大小(实际上是 2**32-1,比 17 大得多)。

“如果”不是这里的论点,则“我不会出错”-您踩踏了用于其他用途的内存。有时用 0 踩下额外的字节并不是致命的(例如,由于对齐,这个字节并没有被使用,或者恰好已经是 0)或者不会导致硬崩溃 - 它不会使其正确。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-27
    • 1970-01-01
    • 2017-08-01
    • 2020-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多