教程 > Lua 教程 > Lua 高级 阅读:92

Lua 调试

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

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

序号 方法 用途
1 debug() 进入一个用户交互模式,运行用户输入的每个字符串。 使用简单的命令以及其它调试设置,用户可以检阅全局变量和局部变量, 改变变量的值,计算一些表达式,等等。
输入一行仅包含 cont 的字符串将结束这个函数, 这样调用者就可以继续向下运行。
2 getfenv(object) 返回对象的环境变量。
3 gethook(optional thread) 返回三个表示线程钩子设置的值: 当前钩子函数,当前钩子掩码,当前钩子计数
4 getinfo ([thread,] f [, what]) 返回关于一个函数信息的表。 你可以直接提供该函数, 也可以用一个数字 f 表示该函数。 数字 f 表示运行在指定线程的调用栈对应层次上的函数: 0 层表示当前函数(getinfo 自身); 1 层表示调用 getinfo 的函数 (除非是尾调用,这种情况不计入栈);等等。 如果 f 是一个比活动函数数量还大的数字, getinfo 返回 nil。
5 debug.getlocal ([thread,] f, local) 此函数返回在栈的 f 层处函数的索引为 local 的局部变量 的名字和值。 这个函数不仅用于访问显式定义的局部变量,也包括形参、临时变量等。
6 getmetatable(value) 把给定索引指向的值的元表压入堆栈。如果索引无效,或是这个值没有元表,函数将返回 0 并且不会向栈上压任何东西。
7 getregistry() 返回注册表表,这是一个预定义出来的表, 可以用来保存任何 C 代码想保存的 Lua 值。
8 getupvalue (f, up) 此函数返回函数 f 的第 up 个上值的名字和值。 如果该函数没有那个上值,返回 nil 。 以 '(' (开括号)打头的变量名表示没有名字的变量 (去除了调试信息的代码块)。
10 sethook ([thread,] hook, mask [, count]) 将一个函数作为钩子函数设入。 字符串 mask 以及数字 count 决定了钩子将在何时调用。 掩码是由下列字符组合成的字符串,每个字符有其含义:
  • 'c': 每当 Lua 调用一个函数时,调用钩子;
  • 'r': 每当 Lua 从一个函数内返回时,调用钩子;
  • 'l': 每当 Lua 进入新的一行时,调用钩子。
11 setlocal ([thread,] level, local, value) 这个函数将 value 赋给 栈上第 level 层函数的第 local 个局部变量。 如果没有那个变量,函数返回 nil 。 如果 level 越界,抛出一个错误。
12 setmetatable (value, table) 将 value 的元表设为 table (可以是 nil)。 返回 value。
13 setupvalue (f, up, value) 这个函数将 value 设为函数 f 的第 up 个上值。 如果函数没有那个上值,返回 nil 否则,返回该上值的名字。
14 traceback ([thread,] [message [, level]]) 如果 message 有,且不是字符串或 nil, 函数不做任何处理直接返回 message。 否则,它返回调用栈的栈回溯信息。 字符串可选项 message 被添加在栈回溯信息的开头。 数字可选项 level 指明从栈的哪一层开始回溯 (默认为 1 ,即调用 traceback 的那里)。

上表列出了我们常用的调试函数,接下来我们可以看些简单的例子:

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

运行示例

执行以上代码输出结果如下所示:

lua 调试示例

在上面的示例程序中,堆栈跟踪是使用调试库中提供的 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 - 具有远程调试、本地调试、语法突出显示、完成建议列表、参数命题引擎、高级断点管理(包括断点和命中计数的条件系统)、函数列表、全局和局部变量列表、监视、面向解决方案的管理。

查看笔记

扫码一下
查看教程更方便