Skip to content

Latest commit

 

History

History
121 lines (79 loc) · 3.39 KB

0X49调试.md

File metadata and controls

121 lines (79 loc) · 3.39 KB

0X49 调试

前置知识

  • 0X44 垃圾回收
  • 0X46 异常处理
  • 0X48 线程调度

简介

调试功能需要使用debug模块.它仅仅提供了一些基本功能,而没有实现常见的完整调试器.

另外官方不建议滥用这个库,详见官方书籍.

交互式调试

调用debug.debug函数可以启动一个交互式的调试环境.这个交互式环境类似于Lua的默认的交互式编程环境,可以查看,修改一些变量并且计算一些表达式.但是它主要用于在程序出现异常的时候启动,用于查看变量以分析异常出现的原因.

要退出交互式调试环境,输入:

cont

修改元表

debug库中也有setmetatable和getmetatable函数.和不加debug前缀的这两个函数并不是同一个函数.但是不知道为什么要单独设置这一组函数.

栈等级

所谓的栈是一种数据结构,用于在管理函数调用时候的内存.这里我不打算详细介绍栈,仅仅描述一下栈等级的概念.

这个概念和函数调用有关.如果一个函数内部调用了另一个函数.假设内部函数的等级为n,则调用它的函数的等级是n+1.可以认为这个'函数等级'就是这一层函数对应的栈等级.

debug.getinfo函数调用的时候可以传入一个整数作为参数.这个整数就表示调用等级.然后就会返回一个包含对应栈等级(对应函数)的信息的表.0表示debug.getinfo这个函数本身,1表示调用debug.getinfo的函数等级.

getinfo还有其他用法,详见官方手册.

获取局部变量

debug.getlocal用于获取局部变量.它接收两个参数,第一个是栈等级,第二个是局部变量的编号(用整数表示,-1表示最后一个局部变量).

例如:

do
local a,b,c,d=22,33,44,55
debug.getlocal(1,1)
debug.getlocal(1,2)
debug.getlocal(1,-1)
end

与getlocal对应的还有一个setlocal函数,用于设置局部变量值.

获取函数上值

所谓的上值就是函数外部的函数可以访问的变量.例如闭包中被外层函数闭包起来的变量.debug.getupvalue可以用于获取函数上值.与getlocal不同的是,getupvalue的第一个参数是一个函数而不是一个整数.

例如:

function creator ()
    local x =0
    local f = function ()
        print(x)
        x=x+1
    end
    return f
end

a=creator()

debug.getupvalue(a,1)
debug.getupvalue(a,2)
a()
a()
debug.getupvalue(a,2)

还可以用upvalueid来检查不同函数的上值是不是共享同一个内存空间.这个函数会返回一个userdata类型的数据.例如:

print(debug.upvalueid(a,2))
b=a
print(debug.upvalueid(b,2))
d=creator()
print(debug.upvalueid(d,2))

改变上值

与debug.getupvalue对应的还有一个debug.setupvalue,用于改变上值.

也可以用debug.upvaluejoin函数.它可以改变闭包变量之间的关系.把一个闭包函数中的闭包变量给另一个闭包函数.

查看注册表值

使用这条命令可以查看注册表值:

debug.getregistry()

所谓的注册表中包含标准io输入输出流对应的地址等信息.

其他函数简介

debug.traceback会返回一条栈追踪信息(返回的字符串格式有点像代码异常时候的提示,但是这就是它的正常返回值).例如:

s=debug.traceback()
type(s)
print(s)

debug.getuservalue和debug.setuservalue用于对userdata类型的处理.

后续推荐

  • 0X4A Hooks