使用ulua等unity lua 脚本接口工具时,经常会出现各种崩溃
这些崩溃本质上有一个共同模式: C#调用 Lua, Lua调用c#, 接着C#出现异常
也就是跨语言 异常处理上 存在严重问题;
ulua,slua等 库 都抄袭了一个叫做 LuaInterface的库, 而这个异常传递导致崩溃的问题,就是LuaInterface自身 设计的问题
修改起来也很简单,避免将C#层的异常,抛给Lua去处理
直接在C#层打印Log,也可以将当前Lua堆栈打Log,同时向Lua层返回一个 nil即可
这个问题本质原因是:
Lua如果使用c编译,使用的longjmp方式处理的异常,c++编译器的话,使用的是c++自己的异常机制;
而C# 是托管代码,走的是Mono虚拟机上的异常处理,
而异常处理,本质上还是要借用 操作系统级别上的 接口
当异常发生的时候,Mono需要 做一次上下文的长跳转,将C#堆栈还原到特定位置,同时需要将 CPU的关键寄存器状态进行还原,C层堆栈进行还原
这里我们就会看到严重的问题,lua的异常机制会对c层,操作系统层堆栈进行处理,而Mono虚拟机也会对操作系统层堆栈进行处理, 我们都知道,两个不会考虑彼此的系统,同时操作一个东西,将会造成怎样的后果
因此我们得出了一个通用方案:
任何跨语言的操作,都要避免异常传递, 例如C++调用C#,C#需要自己捕获异常,lua调用c# c#调用lua 都需要将异常在语言内部消化,而不要外漏
参考:
http://www.mono-project.com/docs/advanced/runtime/docs/exception-handling/