c - 在lua中设置不同的内存分配函数

标签 c memory-management lua

我正在做 Roberto Ierusalimschy 所著的《Programming in 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->frealloc)(g->ud, block, osize, nsize);

使用的Lua版本是5.2.3。

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

最佳答案

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

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

关于c - 在lua中设置不同的内存分配函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20709938/

相关文章:

multithreading - 使用线程时的内存管理

lua - 使用lua模拟登录

events - WOW插件开发/事件

c - 线程安全地初始化一个指针一次

c - 为什么我的解压缩显示错误?

c - 为什么需要execstack才能在堆上执行代码?

c - 为什么Lua C函数中的参数值显示在堆栈底部?

python - 将 Python 字典转换为类 C 结构

python - 如何从内存中手动删除张量?

c++ - 与竞争特定内存地址(互斥锁暂停另一个)相比,circularBuffer 如何提高性能?