简单 Lua 协同程序测试首先崩溃 运行

simple Lua corotine test crashed at first run

简而言之,测试程序在 C++ 端创建一个协程,用 Lua 端函数启动它,并使用一些日志恢复几次。它在第一次调用启动协程 运行 的 resume 时突然崩溃,侵犯了对无效堆内存的访问权限 (0xfdfdfd)。

这是完整的代码:

#include <juce_core/juce_core.h>
#include <lauxlib.h>

int debug_log( lua_State* lua )
{
    int narg = lua_gettop( lua );
    juce::StringArray tokens;
    for ( int i = 1; i <= narg; i++ )
        tokens.add( lua_tostring( lua, i ) );
    juce::Logger::writeToLog( tokens.joinIntoString( "" ) );
    return 0;
}

const char* lua_code =
    "function testfunc(arg1, arg2)\n"
    "    debug_log( \"before yield: arg1 \", arg1 )\n"
    "    coroutine.yield(1)\n"
    "    debug_log( \"after yield: arg2 \", arg2 )\n"
    "    coroutine.yield(2)\n"
    "    debug_log( \"finally in testfunc\" )\n"
    "end\n";

int main()
{
    auto* lua = luaL_newstate();
    luaL_openlibs( lua );
    lua_pushcfunction( lua, debug_log );
    lua_setglobal( lua, "debug_log" );
    luaL_dostring( lua, lua_code );

    // create a new coroutine
    auto* coro = lua_newthread( lua );

    // start corotine
    int t_testfunc = lua_getglobal( coro, "testfunc" );
    if ( t_testfunc != LUA_TFUNCTION )
    {
        juce::Logger::writeToLog( "failed to get testfunc from coro: type is " + juce::String( t_testfunc ) );
        exit( EXIT_FAILURE );
    }

    lua_pushstring( coro, "arg1" );
    lua_pushnumber( coro, 123.456 );
    int n_re = 0;
    int status = lua_resume( lua, coro, 2, &n_re ); ///< die here

    // repeatedly resume until finished
    while ( true )
    {
        juce::Logger::writeToLog( "status: " + juce::String( status ) + " with " + juce::String( n_re ) + " returned values" );
        if ( n_re > 0 )
        {
            juce::Logger::writeToLog( "  returned value " + juce::String( lua_tostring( coro, 1 ) ) );
            lua_pop( coro, n_re );
        }
        if ( status == LUA_YIELD )
        {
            status = lua_resume( lua, coro, 0, &n_re );
        }
        else if ( status == LUA_OK )
        {
            juce::Logger::writeToLog( "coroutine ended" );
            break;
        }
        else
        {
            juce::Logger::writeToLog( "coroutine returned with error: " + juce::String( status ) );
            exit( EXIT_FAILURE );
        }
    }
}

这是堆栈跟踪:

>   coro_call.exe!luaH_getshortstr(Table * t, TString * key) 行 751  C++
    coro_call.exe!luaT_gettmbyobj(lua_State * L, const TValue * o, TMS event) 行 83  C++
    coro_call.exe!luaD_tryfuncTM(lua_State * L, StackValue * func) 行 391    C++
    coro_call.exe!luaD_precall(lua_State * L, StackValue * func, int nresults) 行 559    C++
    coro_call.exe!ccall(lua_State * L, StackValue * func, int nResults, int inc) 行 575  C++
    coro_call.exe!resume(lua_State * L, void * ud) 行 731    C++
    coro_call.exe!luaD_rawrunprotected(lua_State * L, void(*)(lua_State *, void *) f, void * ud) 行 144  C++
    coro_call.exe!lua_resume(lua_State * L, lua_State * from, int nargs, int * nresults) 行 788  C++
    coro_call.exe!main() 行 44   C++

是不是对Lua协程C有什么误解API?

此外,Lua官方文档对k函数lua_pcallk的概念给出了相当长的部分,但我好像没有在我的测试代码中的任何地方都需要它们。我应该在哪里使用这些东西?

lua_resume
的参数顺序有误 它应该是 lua_resume(coro, lua, 而不是 lua_resume(lua, coro,

concepts of k function ... Where should I use these stuffs?

有一个使用 k 函数的好例子