2013-12-20 1 views
2

저는 Roberto Ierusalimschy의 "Programming in Lua"책의 제 3 판에서 연습하고 있습니다. 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 같은 소스를 구축하고 루아 스크립트에서 사용

,
local memlimit = require"memlimit"
프로그램 충돌 스크립트가 종료됩니다. 문제를 찾기 위해 디버거를 사용할 때 문제가있는 문이 루아 내부에있는 것처럼 보입니다.

newblock = (*g->frealloc)(g->ud, block, osize, nsize);

루아의 사용 버전은 5.2.3이다 :이 파일은 lmem.c 라인 84입니다.

루아 메모리 관리를 잘못하려면 어떻게해야합니까?

+0

그 파일에 'newblock = ...'이있는 두 개의 동일한 라인이 있습니다. 그 중 하나입니까? – Schollii

+0

안녕하세요, Schollii. 위의 코드 줄에서 언급했듯이 질문 된 줄은 84입니다. – bobeff

+0

죄송합니다. 나는 좀비였습니다! – Schollii

답변

2

내가 코드를 시도했지만 여기에 내가 그것을 읽을 때 내 관심을 끌었 무엇을하지 않은 :

udluaopen_memlimit에이 유저 데이터로 생성되지만 루아에 고정되지 않습니다. lua_getallocf으로 전달하면 앵커로 계산되지 않습니다. udl_alloc을 사용하여 모든 데이터를 비우려고 할 때 프로그램이 lua_close을 통해 끝날 때 수집 될 수 있습니다. 평범한 malloc이나 원래의 allocf를 사용하여 ud을 만들어야합니다.

+0

답해 주셔서 감사합니다. 당신은 완전합니다. 나는 userdataum을 레지스트리에 고정시키고 문제는 사라졌다. – bobeff