lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

Richard Hundt wrote:
> I've got a question about the intended behaviour of VLA's, though.
> What's the canonical way to resize them? I don't get the "Variable
> Length" part of "Variable Length Array". Do we use ffi.C.realloc and
> friends, or is it smarter than that?

The length of a VLA is variable at creation time. But it's not
variable afterwards. It's not meant as a resizable buffer.

The rationale for VLA's is to have a single ctype which can be
reused to create arrays of varying sizes. So you can do this:

  local charbuf = ffi.typeof("char[?]")
  local buf20  = charbuf(20)
  local buf100 = charbuf(100)

If you really want a dynamically resizable array, the canonical
way is to do it like in C: manage a pointer plus a length, use
explicit resizes and replace the pointer with the result of
realloc and manually free the memory at the end (the pointer
itself is GC'ed).

You can wrap this in a proxy table and check the index against the
length in __newindex, if you want automatic resizes. Or you could
just use Lua tables. :-)

The FFI only provides low-level structures -- you build the

> The following segfaults on my box:
> local ffi = require("ffi")
> ffi.cdef[[
>    int sprintf(char *str, const char *format, ...);
> ]]
> local buf ="char[?]", 16)
> ffi.C.sprintf(buf, "%s", string.rep("x", 17)) -- buffer overflow?

Most certainly. You're writing 17+1 bytes into a 16 byte buffer.

Umm, did you expect it to somehow magically resize? Only sprintf
knows how many characters are needed. It just gets a pointer to a
buffer and blindly writes to it. Sure, there's snprintf and even
asprintf, but neither of them resize anything.

Note that the buffer returned from asprintf is created with malloc
and needs to be manually released with free(). There's no GC for
that, of course. In general, and malloc()/free() do
not mix -- these are two completely different mechanisms.