【问题标题】:set different memory allocation function in lua在lua中设置不同的内存分配函数
【发布时间】:2013-12-21 07:33:25
【问题描述】:

我正在做 Roberto Ierusalimschy 的第三版“Lua 编程”一书中的练习。我在练习 32.1 的解决方案中有一个错误问题。该语句在代码中作为注释提供。

/*
  Exercise 32.1:
    Write a library that allows a script to limit the total amount of memory
used by its Lua state. It may offer a single function, setlimit, to set that
limit.
    The library should set its own allocation funciton. This function, before
calling the original allocator, checks the total memory in use and returns
NULL if the requested memory exeeds the limit.
    (Hint: the library can use lua_gc to initialize its byte count when it
starts. It also can use the user data of the allocation function to keep its
state: the byte count, the current memory limit, etc.; remember to use the
original user data when calling the original allocation function.)
*/

#ifdef WIN32
  #define LUA_EXPORT __declspec(dllexport)
#else
  #define LUA_EXPORT
#endif

#include <lauxlib.h>

typedef struct MemLimitUData
{
  size_t mem_limit;
  size_t currently_used;
  lua_Alloc original_alloc;
  void *original_ud;
}
MemLimitUData;

static int l_setlimit(lua_State *L)
{
  MemLimitUData *ud;
  size_t mem_limit = luaL_checkinteger(L, 1);

  lua_getallocf(L, &ud);
  ud->mem_limit = mem_limit;

  return 0;
}

static int l_getlimit(lua_State *L)
{
  MemLimitUData *ud;

  lua_getallocf(L, &ud);
  lua_pushnumber(L, ud->mem_limit);

  return 1;
}

static void *l_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
{
  MemLimitUData *udata = (MemLimitUData*)ud;

  if (udata->mem_limit != 0 &&
      udata->mem_limit < udata->currently_used - osize + nsize)
  {
    return NULL;
  }

  udata->currently_used += nsize - osize;
  return udata->original_alloc(udata->original_ud, ptr, osize, nsize);
}

static const luaL_Reg memlimit[] =
{
  { "setlimit", l_setlimit },
  { "getlimit", l_getlimit },
  { NULL, NULL }
};

int LUA_EXPORT luaopen_memlimit(lua_State *L)
{
  MemLimitUData *ud =
    (MemLimitUData*)lua_newuserdata(L, sizeof(MemLimitUData));

  ud->mem_limit = 0;
  ud->currently_used =
    lua_gc(L, LUA_GCCOUNT, 0) * 1024 + lua_gc(L, LUA_GCCOUNTB, 0);
  ud->original_alloc = lua_getallocf(L, &ud->original_ud);

  lua_setallocf(L, l_alloc, ud);
  luaL_newlib(L, memlimit);

  return 1;
}

当我将源构建为 memlimit.dll 并从 Lua 脚本中使用它时,

local memlimit = require"memlimit"
脚本结束时程序崩溃。当我使用调试器查找问题时,有问题的语句似乎在 Lua 内部。该文件是 lmem.c84
newblock = (*g-&gt;frealloc)(g-&gt;ud, block, osize, nsize);

使用的Lua版本是5.2.3。

我做错了什么来破坏 Lua 内存管理?

【问题讨论】:

  • 该文件中有两行相同的newblock = ...,是哪一行?
  • 嗨,Schollii。上面提到的代码行,有问题的行是84。
  • 没问题。感谢您的帮助。

标签: c memory-management lua


【解决方案1】:

我还没有尝试过你的代码,但是当我阅读它时,这引起了我的注意:

luaopen_memlimit 中的ud 是作为用户数据创建的,但并未锚定在 Lua 中。将其传递给lua_getallocf 不算作锚定。当程序通过lua_close 结束时,当它尝试使用您的l_alloc 释放所有数据时,可能正在收集ud。您可能应该使用普通的malloc 或原始的allocf 来创建ud

【讨论】:

  • 感谢您的回答。你是完全正确的。我将 userdataum 锚定在注册表中,问题就消失了。
猜你喜欢
  • 2012-06-19
  • 2021-09-09
  • 2019-06-12
  • 2023-04-01
  • 1970-01-01
  • 2012-06-02
  • 1970-01-01
  • 2012-05-03
  • 2012-12-26
相关资源
最近更新 更多