Lua 调试库( debug )

一、调试库作用

使用调试库可以获取 Lua 环境运行过程中的变量和跟踪代码执行。

调试库主要分为两类函数:自省函数和钩子函数

  • 自省函数:允许检查一个正在运行中的程序,例如活动函数的栈、当前正在执行的代码行、局部变量的名称和值。
  • 钩子函数:允许跟踪一个程序的执行。

值得注意:

调试库的某些功能性能不高,而且会打破语言的一些固有规则。

二、自省函数

1、debug.getinfo(thread, f, what)

该函数会返回包含函数信息的表。

参数:

  • thread: 表示在 thread 中获取相应的信息
  • f: 可以给两种模式,函数或数值。第一种则是给函数,获取给定函数的信息表。第二种则是给一个数字作为 f 的值,表示栈层级:当为 0 时表示当前函数( 即 getinfo 本身), 1 表示调用 getinfo 的函数(尾调用除外,它们不计入堆栈),以此类推。如果 f 是一个大于活跃栈层级的数字,则 getinfo 返回 nil
  • what: 可选项,表示要获取哪些指定的信息。因为 getinfo 的效率不高,所以为了效率好些,可以只选择需要的内容,如果需要多个值时,可以将多个拼凑,例如 nfS
what 取值 获取的值
n 选择 name 和 namewhat
f 选择 func
S 选择 source、short_src、what、linedefined 和 lastlinedefined
l 选择 currentline
L 选择 activelines
u 选择 nup、nparams 和 isvararg

这些字段的含义如下:

字段 描述
name 该字段是该函数的一个适当的名称,例如保存该函数的全局变量的名称。(可能没有值,也可能有多个名称)(只有当 f 为数值时才有该值)
namewhat 该字段用于说明 name 字段的含义,可能是 “global”、“local”、“method”、“field” 或 “”(空字符串)。空字符串表示 Lua 语言找不到该函数的名称。
func 该字段是该函数本身
source 该字段用于说明函数定义的位置。如果函数定义在一个字符串中(通过调用 load),那么 source 就是这个字符串;如果函数定义在一个文件中,那么 source 就是使用 @ 作为前缀的文件名
short_src 该字段是 source 的精简版本(最多 60 个字符),对于错误信息十分有用。
what 该字段用于说明函数的类型。
- 如果 foo 是一个普通的 Lua 函数,则为 “Lua”
- 如果是一个 C 函数,则为 “C”
- 如果是一个 Lua 语言代码段的主要部分,则为 “main” 。
linedefined 该字段是该函数定义在源代码中第一行的行号
lastlinedefined 该字段是该函数定义在源代码中最后一行的行号
currentline 表示当前该函数正在执行的代码所在的行 (只有当 f 为数值时才有该值)
istailcall 返回一个布尔值,为真表示函数是被尾调用所调起(尾调用时,函数真正的调用者不在栈中)(只有 f 为数值时才有该值)
activelines 该字段是一个包含该函数所有活跃行的集合。活跃行是指除空行和只包含注释的行外的其它行(该字段的典型用法是用于设置断点。大多数调试器不允许在活跃行外设置断点,因为非活跃行是不可达的)。
nups 该字段是该函数的上值的个数
nparams 该字段是该函数的参数个数
isvararg 该字段表明该函数是否为可变长函数

返回值:

如果传递的是一个函数或是一个合理的数值(小于等于栈层级),则会返回对应函数的信息表。如果超出的栈层级,则返回 nil

值得注意:

如果假设 foo 是一个 C 函数,Lua 语言没有多少关于该函数的信息。只有字段 what、name、namewhat、nups 和 func 是有意义的。

举两个例子:

输出一个函数的信息

function foo(a, b, ...)
    print("江澎涌")
end
local info = debug.getinfo(foo)
for k, v in pairs(info) do
    print(k, "---", v)
end

使用数值调用

foo1 = function(...)
    local table = debug.getinfo(1)
    for k, v in pairs(table) do
        print(k, "---", v)
    end
end
foo1()

上面例子中调用栈的层次如下:

2、traceback(thread, message, level)

返回调用栈信息

参数:

  • thread: 表示在 thread 中获取相应的信息
  • message:该参数没有限定为字符串,可以是任意的类型。如果为字符串或 nil ,则会返回调用栈的描述字符串,并且在最开始的地方拼接该 message (如果为 nil ,则不拼接)。如果为其他类型,则直接放回该值。
  • level:调用层级,0 表示 traceback 函数,1 表示调用 traceback 函数的函数,2 表示调用 traceback 函数的函数的函数 …

返回值:

如果 message 为字符串或 nil ,则会返回调用栈的描述字符串,并且在最开始的地方拼接该 message (如果为 nil ,则不拼接)。如果为其他类型,则直接返回该值。

举个例子

print("没有参数")
local function foo1()
    print(debug.traceback())
end
foo1()

--> 没有参数
--> stack traceback:
--> 	...Lua/lua_study_2022/18 调试库/自省机制-getInfo.lua:58: in local 'foo1'
--> 	...Lua/lua_study_2022/18 调试库/自省机制-getInfo.lua:60: in main chunk
--> 	[C]: in ?

print("携带 message(字符串)")
local function foo2()
    print(debug.traceback("track back message."))
end
foo2()

--> 携带 message(字符串)
--> track back message.
--> stack traceback:
--> 	...Lua/lua_study_2022/18 调试库/自省机制-getInfo.lua:64: in local 'foo2'
--> 	...Lua/lua_study_2022/18 调试库/自省机制-getInfo.lua:66: in main chunk
--> 	[C]: in ?

print("携带 message(非字符串)")
local function foo3()
    print(debug.traceback({
   
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值