C中重新分配/调整Lua 5.1用户数据

如何在运行时用C调整Lua 5.1用户数据对象的大小?

我想从Lua 5.1控制台中更改Roberto Ierusalimschy的书《Programming in Lua,第2版,pp. 260》中描述的NumArray结构的大小。

我的NumArray用户数据可以存储无符号字符或lua_Numbers。我尝试调用在lmem.c中定义的未修改的luaM_realloc_函数,但最终通过调用C的realloc函数(通过l_alloc)返回NULL,因此我会收到“内存不足”的错误消息。

能否有人帮帮我?


LUA_API void *agn_resizeud (lua_State *L, void *block, size_t osize, size_t nsize) {
  Udata *u = (Udata *)luaM_realloc_(L, block, osize + sizeof(Udata), nsize + sizeof(Udata));
  u->uv.len = nsize;
  if (u == NULL)
    luaL_error(L, "Error in " LUA_QS ": failed to allocate memory.", "API/agn_resizeud");
  return u;
}

--- numarray.c ---------------------------------------------------------------------------------------------

#define checkarray(L, n) (NumArray *)luaL_checkudata(L, n, "numarray")

[...]

/* Auxiliary C function to finally call luaM_realloc_ via the Lua C API */

void *reallocud (lua_State *L, void *block, size_t o, size_t n, size_t sizeofelem, size_t sizeofnumarray) {
  if (n + 1 > MAX_SIZET/sizeofelem)
    luaL_error(L, "Error in " LUA_QS ": memory allocation error: block too big.", "(reallocud)", n);
  else
    return agn_resizeud(L, block, sizeofnumarray + o*sizeofelem, sizeofnumarray + n*sizeofelem);
}

/* function to resize a NumArray */

static int numarray_resize (lua_State *L) {
  size_t i;
  global_State *g = G(L);
  NumArray *a = checkarray(L, 1);
  int n = luaL_checkinteger(L, 2);
  if (n < 1)
    luaL_error(L, "Error in " LUA_QS ": new size %d is non-positive.", "numarray.resize", n);
  if (n == a->size) {   /* do nothing and do not complain */
    lua_pushinteger(L, a->size);
    return 1;
  }
  if (n > a->size) {  /* extend */
    a = reallocud(L, a, a->size, n, a->isnumber ? sizeof(lua_Number) : sizeof(char), sizeof(NumArray));
    if (a->isnumber) {
      for (i=a->size; i < n; i++) a->data.n[i] = 0;
    } else {
      for (i=a->size; i < n; i++) a->data.c[i] = 0;
    }
  } else {  /* reduce */
    if (a->isnumber) {
      for (i=a->size - 1; i > n - 1; i--) a->data.n[i] = 0;
    } else {
      for (i=a->size - 1; i > n - 1; i--) a->data.c[i] = 0;
    }
    a = reallocud(L, a, a->size, n, a->isnumber ? sizeof(lua_Number) : sizeof(char), sizeof(NumArray));
  }
  a->size = n;
  lua_pushnumber(L, a->size);
  return 1;
}

[...]

typedef struct NumArray {
  size_t size;           /* number of slots */
  char isnumber;
  union data {
    lua_Number n[1];  /* pointer to the various lua_Number values */
    unsigned char c[1];
  } data;
} NumArray;
点赞
用户2726734
用户2726734
静态整型 numarray_resize (lua_State *L) {

    [...]

    if (n > a->size) {  /* 扩展 */
        a = reallocud(L, a, a->size, n, a->isnumber ? sizeof(lua_Number) : sizeof(char), sizeof(NumArray));
        if (a->isnumber) {

  [...]

realloc 需要 2 个参数,你需要 reallocud

使用大小为 aL 进行 realloc 可能会得到一个巨大的数字,而且 L 可能从未被 alloc 系列分配,所以有几个原因会出现意外的 NULL

2015-04-22 23:02:32
用户107090
用户107090

无需操作 Lua 的内部。

但你需要改变userdata的创建方式:不再在同一个内存块中分配结构体和数据,而是分别使用 lua_newuserdata 分配结构体和 malloc 分配数据。

然后,要调整数据部分的大小,只需更新结构体中的大小,然后使用 realloc 调整数据部分。

2015-04-23 00:00:18