如何在Lua中修复“堆栈溢出”错误?

我正在尝试修复一个在Payday 2 BLT mod中导致游戏崩溃的问题,但我是一个新手,对于modding和Lua都不熟悉,作者已经超过一年没有更新了,我设法将崩溃跟踪到脚本的第13行:

这是错误信息:

应用程序崩溃:C++ 异常
mods/ShadowRaidLoud/lua/coremissionscriptelement.lua:13: 堆栈溢出

据我所知,tostring(self._id)可能导致错误,但我不知道该怎么办。

这是一个Payday 2 mod,删除这个mod可能会停止崩溃,但我想自己修复它。 尝试联系作者,但没有成功。

coremissionscriptelement.lua:

core:module("CoreMissionScriptElement")
core:import("CoreXml")
core:import("CoreCode")
core:import("CoreClass")

_G.ShadowRaidLoud = _G.ShadowRaidLoud or {}
ShadowRaidLoud = _G.ShadowRaidLoud
ShadowRaidLoud.Run_Script_Data = ShadowRaidLoud.Run_Script_Data or {}

local ShadowRaidLoud_OpenVault = MissionScriptElement.on_executed

function MissionScriptElement:on_executed(instigator, ...)
    local _id = "id_" .. tostring(self._id)   -- 此处发生堆栈溢出崩溃
    if ShadowRaidLoud and ShadowRaidLoud.Enable and not Network:is_client() then
        if (_id == "id_100961" or _id == "id_100962") and not ShadowRaidLoud.Run_Script_Data[_id] then
            local element = self:get_mission_element(100964)
            if element then
                local msg = "[System] 金库将在 ".. ShadowRaidLoud.Time4Use.OpenVault .." 秒后打开"
                ShadowRaidLoud:Announce(msg)
                local _tmp = ShadowRaidLoud:Run_Script("id_100964", self, 100964, element, instigator, ShadowRaidLoud.Time4Use.OpenVault)
                ShadowRaidLoud.Run_Script_Data["id_100961"] = _tmp
                ShadowRaidLoud.Run_Script_Data["id_100962"] = _tmp
            end
        end
    end
    ShadowRaidLoud_OpenVault(self, instigator, ...)
end

编辑:我尝试在函数的最后一行添加返回,但仍然导致崩溃,并出现以下崩溃日志:

应用程序崩溃:访问冲突

-------------------------------

调用堆栈:

         payday2_win32_release  (???)     ???

-------------------------------

当前线程:LoadingEnvironment

-------------------------------

系统信息:
    应用程序版本:1.92.790
    CPU:Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz(2核心);SSE;SSE2;SSE3;SSSE3;SSE4.1;SSE4.2
    DirectX:12.0
    GPU:NVIDIA GeForce GTX 1070 / nvldumd.dll[26.21.14.3160]
    语言:英语
    存储器:16269MB 264KB
    操作系统:6.1.7600()0x300-0x164位)
    物理特性:多线程
    渲染器:DX9 多线程
    声音:Realtek Semiconductor Corp.(扬声器(Realtek High Definition Audio))
点赞
用户1244588
用户1244588

很难测试是否只有这个问题,但是正如 @Egor 已经提到的,hadowRaidLoud_OpenVault == MissionScriptElement.on_executed,你应该在 ShadowRaidLoud_OpenVault(self, instigator, ...) 之前加入一个返回语句,将它转变成一个适当的尾调用:

function MissionScriptElement:on_executed(instigator, ...)
    --- SNIP ---
    return ShadowRaidLoud_OpenVault(self, instigator, ...)
end

至少,在满足尾调用的要求的情况下,递归不应再次导致堆栈溢出。

2019-08-11 12:48:25