Lua - 调试

Lua 提供了一个调试库,它为我们提供了所有的原始函数来创建自己的调试器。 尽管没有内置的 Lua 调试器,但我们有许多 Lua 调试器,由各种开发人员创建,其中许多是开源的。

下表列出了 Lua 调试库中可用的函数及其用途。

序号 方法 & 用途
1

debug()

进入调试的交互模式,在我们只在一行中输入 cont 并按回车之前,它一直处于活动状态。 用户可以在此模式下使用其他功能检查变量。

2

getfenv(object)

返回对象的环境。

3

gethook(optional thread)

返回线程的当前 hook 设置,作为三个值 − 当前 hook 函数、当前 hook 掩码和当前 hook 计数。

4

getinfo(optional thread, function or stack level, optional flag)

返回一个包含函数信息的表。 可以直接给出函数,也可以给出一个数字作为函数的值,表示该函数运行在给定线程的调用栈的函数级别 − 0 级是当前函数(getinfo 本身); 级别 1 是调用 getinfo 的函数; 等等。 如果 function 的数量大于活动函数的数量,则 getinfo 返回 nil。

5

getlocal(optional thread, stack level, local index)

返回堆栈级别函数的局部变量的名称和值。如果没有具有给定索引的局部变量,则返回 nil,并在调用级别超出范围时引发错误。

6

getmetatable(value)

返回给定对象的元表,如果没有元表,则返回 nil。

7

getregistry()

返回注册表,这是一个预定义的表,任何 C 代码都可以使用它来存储它需要存储的任何 Lua 值。

8

getupvalue(function, upvalue index)

此函数返回函数 func 的索引为 up 的 upvalue 的名称和值。 如果给定索引没有上值,则该函数返回 nil。

9

setfenv(function or thread or userdata, environment table)

将给定对象的环境设置为给定表。 返回对象。

10

sethook(optional thread, hook function, hook mask string with "c" and/or "r" and/or "l", optional instruction count)

将给定函数设置为 hook。 字符串掩码和数字计数描述了何时调用 hook。 在这里,每次 Lua 调用、返回和进入函数中的每一行代码时,都会分别调用 c、r 和 l。

11

setlocal(optional thread, stack level, local index, value)

将值分配给具有堆栈级别函数的索引 local 的局部变量。 如果没有具有给定索引的局部变量,则该函数返回 nil,并在调用超出范围的级别时引发错误。 否则,它返回局部变量的名称。

12

setmetatable(value, metatable)

将给定对象的元表设置为给定表(可以为 nil)。

13

setupvalue(function, upvalue index, value)

此函数将值分配给函数 func 的索引向上的向上值。 如果给定索引没有上值,则该函数返回 nil。 否则,它返回上值的名称。

14

traceback(optional thread, optional message string, optional level argument)

构建带有回溯的扩展错误消息。

上面的列表是 Lua 中调试函数的完整列表,我们经常使用使用上述函数并提供更容易调试的库。 使用这些函数并创建我们自己的调试器非常复杂,并不可取。 无论如何,我们将看到一个简单使用调试功能的示例。

function myfunction ()
   print(debug.traceback("Stack trace"))
   print(debug.getinfo(1))
   print("Stack trace end")

   return 10
end

myfunction ()
print(debug.getinfo(1))

当我们运行上面的程序时,我们将得到如下所示的堆栈跟踪。

Stack trace
stack traceback:
	test2.lua:2: in function 'myfunction'
	test2.lua:8: in main chunk
	[C]: ?
table: 0054C6C8
Stack trace end

在上面的示例程序中,堆栈跟踪是使用调试库中提供的 debug.trace 函数打印的。 debug.getinfo 获取函数的当前表。


调试 - 示例

我们经常需要知道函数的局部变量来进行调试。 为此,我们可以使用 getupvalue 并设置这些局部变量,我们使用 setupvalue。 一个简单的例子如下所示。

function newCounter ()
   local n = 0
   local k = 0
	
   return function ()
      k = n
      n = n + 1
      return n
   end
	
end

counter = newCounter ()

print(counter())
print(counter())

local i = 1

repeat
   name, val = debug.getupvalue(counter, i)
	
   if name then
      print ("index", i, name, "=", val)
		
      if(name == "n") then
         debug.setupvalue (counter,2,10)
      end
		
      i = i + 1
   end -- if
	
until not name

print(counter())

当我们运行上述程序时,我们将得到以下输出。

1
2
index	1	k	=	1
index	2	n	=	2
11

在此示例中,计数器每次被调用时都会更新一。 我们可以使用 getupvalue 函数查看局部变量的当前状态。 然后我们将局部变量设置为一个新值。 这里,在调用 set 操作之前,n 为 2。 使用 setupvalue 函数,将其更新为 10。现在当我们调用 counter 函数时,它将返回 11 而不是 3。


调试类型

  • 命令行调试
  • 图形调试

命令行调试

命令行调试是一种使用命令行在命令和打印语句的帮助下进行调试的调试类型。 Lua 有许多可用的命令行调试器,下面列出了其中的一些。

  • RemDebug − RemDebug 是 Lua 5.0 和 5.1 的远程调试器。 它可以让你远程控制另一个 Lua 程序的执行,设置断点和检查程序的当前状态。 RemDebug 还可以调试 CGILua 脚本。

  • clidebugger − 一个用纯 Lua 编写的 Lua 5.1 的简单命令行界面调试器。 它不依赖于标准 Lua 5.1 库以外的任何东西。 它的灵感来自 RemDebug,但没有远程工具。

  • ctrace − 用于跟踪 Lua API 调用的工具。

  • xdbLua − 适用于 Windows 平台的简单 Lua 命令行调试器。

  • LuaInterface - Debugger − 该项目是 LuaInterface 的调试器扩展。 它将内置的 Lua 调试接口提升到更高的水平。 与调试器的交互是通过事件和方法调用完成的。

  • Rldb − 这是一个通过套接字的远程 Lua 调试器,可在 Windows 和 Linux 上使用。 它可以为您提供比任何现有功能更多的功能。

  • ModDebug − 这允许远程控制另一个 Lua 程序的执行、设置断点并检查程序的当前状态。

图形调试

图形调试可在 IDE 的帮助下使用,您可以在其中对变量值、堆栈跟踪和其他相关信息等各种状态进行可视化调试。 借助 IDE 中的断点、单步执行、单步执行和其他按钮,可以直观地显示并逐步控制执行。

Lua 有许多图形调试器,其中包括以下内容。

  • SciTE − Lua 的默认 Windows IDE 提供了多种调试工具,例如断点、单步调试、单步执行、单步调试、监视变量等。

  • Decoda − 这是一个具有远程调试支持的图形调试器。

  • ZeroBrane Studio − Lua IDE 集成了远程调试器、堆栈视图、监视视图、远程控制台、静态分析器等。 适用于 LuaJIT、Love2d、Moai 和其他 Lua 引擎; Windows、OSX 和 Linux。 开源。

  • akdebugger − Eclipse 的调试器和编辑器 Lua 插件。

  • luaedit − 这具有远程调试、本地调试、语法突出显示、完成建议列表、参数命题引擎、高级断点管理(包括断点和命中计数的条件系统)、函数列表、全局和局部变量列表、监视、面向解决方案的管理。