Crashes when calling `lua_getfield()` after overriding the require

孤人 提交于 2019-12-12 13:00:26

问题


This question is related to @Henri_Menke's answer from this question : How to get preloaded module name in C++

I'm trying to override the require function with my own version so I can get the preloaded module name inside Lua script.

Here's my code:

#include "lua.hpp"

void main()
{
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
    lua_settop(L, 0);
    luaL_dostring(L, "local require_original = require\n"
                     "function require(name, ...)\n"
                         "current_module = name\n"
                         "require_original(name, ...)\n"
                         "current_module = nil\n"
                     "end\n"); //if I comment out this chunk, it works fine
    luaL_dostring(L, "package.preload['test'] = function ()\n"
                         "local test = {}\n"
                         "print('While loading:', current_module)\n"
                         "function test.update() print('Updated!') end\n"
                         "return test\n"
                     "end\n");
    lua_getglobal(L, "require");
    lua_pushstring(L, "test");
    if (lua_pcall(L, 1, LUA_MULTRET, 0))
    {
        std::cout << "Error: " << lua_tostring(L, -1) << std::endl;
        lua_pop(L, 1);
    }
    int top = lua_gettop(L);
    lua_getfield(L, -1, "update"); //crashes here
    if (lua_isfunction(L, -1))
    {
        lua_pushnil(L);
        if (lua_pcall(L, 1, LUA_MULTRET, 0))
        {
            std::cout << "Error: " << lua_tostring(L, -1) << std::endl;
            lua_pop(L, 1);
        }
    }
    lua_close(L);
}

However, it crashes when calling lua_getfield(L, -1, "update");.

And it no longer crashes when I comment out the first chunk of Lua script(first luaL_dostring).

I don't understand why it crashes if I use my own version of require.

How can I fix this?


回答1:


I forgot to return the module table from overridden require function. Sorry about that.

#include <iostream>
#include "lua.hpp"

int main() {
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
    lua_settop(L, 0);
    luaL_dostring(L, "local require_original = require\n"
                     "function require(name, ...)\n"
                         "current_module = name\n"
                         "local val = table.pack(require_original(name, ...))\n"
                         "current_module = nil\n"
                         "return table.unpack(val,1,val.n)\n"
                     "end\n"); //if I comment out this chunk, it works fine
    luaL_dostring(L, "package.preload['test'] = function ()\n"
                         "local test = {}\n"
                         "print('While loading:', current_module)\n"
                         "function test.update() print('Updated!') end\n"
                         "return test\n"
                     "end\n");
    lua_getglobal(L, "require");
    lua_pushstring(L, "test");
    if (lua_pcall(L, 1, LUA_MULTRET, 0))
    {
        std::cout << "Error: " << lua_tostring(L, -1) << std::endl;
        lua_pop(L, 1);
    }
    int top = lua_gettop(L);
    lua_getfield(L, -1, "update"); //crashes here
    if (lua_isfunction(L, -1))
    {
        lua_pushnil(L);
        if (lua_pcall(L, 1, LUA_MULTRET, 0))
        {
            std::cout << "Error: " << lua_tostring(L, -1) << std::endl;
            lua_pop(L, 1);
        }
    }
    lua_close(L);
}
$ clang++ -Wall -Wextra -Wpedantic -I /usr/include/lua5.2 test.cpp -llua5.2
test.cpp:28:9: warning: unused variable 'top' [-Wunused-variable]
    int top = lua_gettop(L);
        ^
1 warning generated.
$ ./a.out 
While loading:  test
Updated!


来源:https://stackoverflow.com/questions/51520697/crashes-when-calling-lua-getfield-after-overriding-the-require

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!