Skip to content

6.10 - 调试库

该库提供了关于Lua程序的调试接口函数。你应当在使用该库时额外小心。这些函数破坏了Lua代码的基本假设(例如,某个函数内的局部变量不可以在外部访问;userdata 的元表不可以在Lua代码中改变;Lua程序不会crash等)并且它们会破坏其他的安全代码。此外,该库中的一些函数可能很慢。

该库中的所有函数都提供在 debug 表中。所有对Lua线程做操作的函数中的第一个参数都是需要操作的Lua线程。其默认为当前线程。

debug.debug ()

进入可交互模式,运行用户输入的每一个字符串。使用简单的命令和其他调试工具,用户可以查看全局或本地变量、改变它们的值、计算表达式等等。一行只包含单词 cont 的输入会结束这个函数,所以调用者代码会在此处之后继续执行。

注意 debug.debug 的命令在词法上没有嵌入到任何函数中,所以你无法通过本地变量直接访问。

debug.gethook ([thread])

返回当前设置在给出Lua线程中的 hook ,有三个值:当前 hook 的函数、当前 hook 的掩码、当前 hook 的数量,同debug.sethook函数。

如果没有活跃的 hook 则返回fail

debug.getinfo ([thread,] f [, what])

返回带有某个函数的相关信息的表。你可以直接给定一个函数,或者你可以给定一个数字作为参数 f ,意思是运行在给定Lua线程的调用栈的第 f 层的函数:0层为当前函数(getinfo 函数自身);1层为调用 getinfo 的函数(尾调用除外,其不在调用栈计数中);以此类推。如果 f 是一个大于活跃数量的数字,则 geinfo 返回fail

这里返回的表中所能包含的字段同lua_getinfo,字符串参数 what 描述了那些要填充的字段。参数 what 默认获取所有可用的信息,除了有效行的表。如果有选项 'f' 则会将该函数自身添加到一个名为 func 的字段上。如果有选项 'L' 则会将有效行的表添加到名为 activelines 的字段上。

例如,表达式 debug.getinfo(1,"n").name 会返回当前函数的名称,如果可以找到合理的名称的话。表达式 debug.getinfo(print) 则会返回带有print函数所有相关信息的表。

debug.getlocal ([thread,] f, local)

返回在某个函数中 local 索引处的局部变量的名称和值,该函数位于调用栈上的第 f 层。该函数不但可以访问本地变量,也可以访问闯入的参数和临时变量。

第一个参数或本地变量的索引是1,以此类推,往后的顺序都依据代码中的声明先后而来,此处只计数函数的当前作用域中的活跃变量。编译时的常量可能并没有加在声明列表中,其会被编译器优化掉。负数索引引用了可变参数:-1表示第一个可变参数。当给出索引处没有变量时该函数会返回fail,并在超出调用层数时抛出一个错误。(你可以调用debug.getinfo来检查给定的层数是否有效。)

由 '(' (开圆括号)打头的变量名表示变量的名称未知(例如像循环控制变量之类的内部变量,以及代码块中没有调试信息的变量)。

参数 f 也可以是个函数。在这种情况下,getlocal 只返回该函数中各个参数的名称。

debug.getmetatable (value)

返回给定 value 的元表,没有元表则返回nil

debug.getregistry ()

返回注册表(参见4.3)。

debug.getupvalue (f, up)

返回在函数 f 中索引为 up 的 upvalue 的名称和值。不存在相应 upvalue 则返回fail

(对于Lua函数,upvalue 是在该函数中使用的外部局部变量,随之包含在该闭包中。)

对于C函数,该函数使用空字符串 "" 作为所有 upvalue 的名称。

变量名 '?'(问号)表示该变量的名称未知(代码块中不带调试信息的变量)。

debug.getuservalue (u, n)

返回给出的 userdata 参数 u 对应的第 n 个 user value ,以及一个布尔值,如果没有相应的 user value 时,这个布尔值为false

debug.sethook ([thread,] hook, mask [, count])

设置调试 hook 。字符串参数 mask 和数字参数 count 表明了触发 hook 的时机。mask 可以由以下字符组合而成,其各含义为:

  • 'c': 每次发生函数调用时触发 hook 。
  • 'r': 每次发生函数返回时触发 hook 。
  • 'c': 每次执行到下一行代码时触发 hook 。

此外,当 count 不为零时,该 hook 会在每执行 count 条指令后触发。

不带参数调用该函数时,会关闭 hook 。

每当 hook 被触发,其第一个传入的参数为描述了触发事件的字符串:"call"、"tail call"、"return"、"line"、和 "count"。对于行事件,还会将新行的行数作为 hook 的第二个参数传入。在 hook 内部,你可以对第 2 层调用 getinfo 来获取关于当前函数更多的信息。(第0层是 getinfo 函数本身,第一层是这个 hook 函数。)

debug.setlocal ([thread,] level, local, value)

将处于调用栈的第 level 层的函数中索引为 local 的局部变量赋值为 value 。如果没有相应的局部变量,该函数会返回fail,并且如果当 level 超出了调用层数,则会另外抛出一个错误。(你可以调用 getinfo 以确认层数是否有效。)否则,其会返回局部变量的名称。

更多关于变量索引和名称的信息请参考debug.getlocal

debug.setmetatable (value, table)

将给定的 value 的元表设置为给定的 table(可以是个nil)。并返回 value 本身。

debug.setupvalue (f, up, value)

该函数会将函数 f 中索引为 up 的 upvalue 设置为给定值 value 。当不存在相应的 upvalue 时会返回fail。否则会返回上值的名称。

更多关于上值的信息请参考debug.getupvalue

debug.setuservalue (udata, value, n)

将给定的 udata 中的第 n 个 user value 设为 value 值。参数 udata 必须是一个 full userdata 。

返回 usdata,或者当不存在相应的 userdata 和 user value 时返回fail

debug.traceback ([thread,] [message [, level]])

如果 message 未缺省并且既不是个字符串或nil,该函数不会做进一步处理并直接返回 message 。否则会返回一个带上了这个 message 的调用栈回溯信息。可选字符串参数 message 回被加到回溯信息的开头。可选数字参数 level 制定了从调用栈的哪一层开始回溯(默认为1,是调用 traceback 的函数)。

debug.upvalueid (f, n)

返回给定函数中的第 n 个上值的唯一索引(是个 light userdata)。

这个唯一索引使得程序可以分辨不同的闭包是否共享了某个上值。对于Lua闭包所共享的某个上值(即访问同名的外部局部变量)将返回相同的索引。

debug.upvaluejoin (f1, n1, f2, n2)

使得Lua闭包 f1 中的第 n1 个上值引用Lua闭包 f2 中的第 n2 个上值。