lua中的编译执行和错误

来源:互联网 发布:文华源码函数 编辑:程序博客网 时间:2024/06/05 00:47

1.lua中的dofile,loadfile,dostring和loadstring 函数

dofile函数想必都不陌生,我们经常在lua的的交互模式下直接用dofile(“”funcName“”)加载一个lua文件并运行,但实际上loadfile()才做了核心的工作,他会从文件加载一个代码块,但是不运行,仅仅编译该代码块,我们可以这样来定义一个dofile函数
function dofile(arg)local func = assert(loadfile(arg))return func()end
处理一些简单的问题,比如有时候我们测试某个代码块的时候使用dofile更加简单,一次完成整个事情,但是loadfile更加灵活,例如可以让我自己处理错误消息(loadfile只会返回错误消息,自己并不处理),尤其在需要反复执行一个文件的时候,dofile需要每次进行编译,而loadfile仅仅需要编译一次,然后反复调用返回的函数就行了
下面看一下loadstring 和 dostring函数,类似loadfile函数,loadstring函数是从一个字符串中读取代码,并进行编译,例如在lua的加护模式下执行如下代码:
会有上述结果,一般当我们提供给用户自己输入一个lua程序给我们调用时,可以使用loadstring,但是这个函数开销较大,必须谨慎使用,类似于dofile,dostring也是对loadstring函数的一层封装,loadstring也不会引发错误,仅仅返回nil和错误消息,需要我们自己对错误消息进行处理。
其实,lua中有一个真正的读取函数 load()(例如io.read()),load接受一个读取器函数,对程序快进行一次或者多次读取,一般我们在程序块非常大,不能一次性载入内存的时候使用。lua中加载一个程序块仅仅是进行了编译,并返回一个带有变长参数的匿名函数作为中间形式,并没有对函数进行定义,lua中函数的定义是发生在函数调用的时候,假如我们有如下lua文件:
function foo()print("zhou,l,h")end
我们利用loadfile来加载,并进行一些输出来看一下结果:


当我们加载之后foo依然是一个nil值,当我们运行加载后的函数后,foo被定义,此时打印出的是一个函数和他的地址,最后打印了调用foo的结果.当然我们可以对这几个函数做更多的工作,比如模仿其它高级语言,我们创建一个沙箱环境来运行可能有安全隐患的代码,从而使程序更贱健壮

2.lua中的错误处理

同样先来介绍几个函数:error,assert,pcall,xpcall
lua中任何未预期的条件都会产生一个错误,我们可以通过error函数显示的引发一个错误:error(“”this is a error“”),一般放在条件判断语句中,当不满足条件时调用,由于结构比较统一,我们可以用assert函数来代替,和其他高级语言的assert函数一样,在assert参数中指定出现错误时,返回的错误信息


当第一个参数为false或者nil时,把第二个参数当做错误信息返回,也可以不指定第二个参数。
当一个程序出现错误时,一般有两种选择方式,返回错误代码或者引发错误,一些容易避免的我们一般引发错误,但是一些不好避免的我们返回错误代码,在lua中我们使用pcall函数来对错误进行捕捉,我们可以把我们需要运行的代码封装在一个函数里面,通过pcall来调用该函数,
function foo()error("have a error")print("zhou,l,h")endif pcall(foo) then--返回真时的流程print("correctly ")else--捕捉到错误后的流程print("incorrectly")end
其实就类似于c++或者c#中的 try{}catch{} 语句块
通常发生错误时,需要完整的错误信息,只是需要了解的当前的堆栈调用情况,而不仅仅是发火说呢个错误的位置,但是pcall返回错误信息时,已经销毁了调用栈的内容,
如果需要得到一个有意思的调用栈就需要在pcall返回前获取该信息,lua中提供了xpcall函数来完成此项工作,该函数除了接受一个被调用的函数之外,还接受第二个错误处理函数当参数,当错误发生时,lua会在调用栈展开前调用错误处理函数,这样,我们就能在这个函数中利用lua的debug库来收集错误信息了,主要用到两个函数debug.debug和debug.traceback,第一个函数提供一个提示符,让用户检查错误原因,第二个函数会根据调用栈来构建一个错误消息,任何时候都可以使用第二个函数来获取当前的调用栈信息,下面是一些列子:
function foo()error("have a error")endfunction f()foo()endres,message = pcall(f)print(res,"  ",message) 
仅仅会打印出foo中的错误,没有显示f调用foo那部分的堆栈,下面我们使用xpcall来调用:
function foo()error("have a error")endfunction f()foo()endres,message = xpcall(f,function ()return debug.traceback()end)print(res,"  ",message) 下面是堆栈图:
显示了完整的堆栈信息。
到此,lua中的错误处理和编译我们应该有了一定的概念,如果需要更深的了解,可以去看看lua的源码中相关函数的实现,博主水平有限,如有不正确的地方欢迎大家批评指出,晚安。

阅读全文
0 0
原创粉丝点击