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

时间:2017-11-02 10:55:59

标签: lua ffi luajit

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

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>

<div id="myDiv"></div>

运行此代码获取:

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不是16字节,则不会发生这种情况。
  • 如果我删除了我未使用的str,则不会发生这种情况。
  • 如果我将ffi.cdef置于ffi.cdef后面,则不会发生这种情况。

    ffi.new

我尝试使用默认编译器参数的Luajit 2.0.5和Luajit 2.1.0-beta3。

那么,有没有人知道这是怎么发生的,谢谢。

1 个答案:

答案 0 :(得分:1)

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

“我不会得到错误,如果”这里不是一个参数 - 你踩踏用于其他东西的内存。有时用0来重写额外字节并不是致命的(例如由于对齐此字节无论如何都没有使用,或者恰好已经是0)或者不会导致硬崩溃 - 它不能使其正确。