Lua 调试(Debug)

Lua 调试(Debug)

  • 作者:杨梦鸽
  • 校对:翟舒青

Lua 提供了 debug 库用于提供创建我们自定义调试器的功能。Lua 本身并未有内置的调试器,但很多开发者共享了他们的 Lua 调试器代码。

Lua 中 debug 库包含以下函数:

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

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 库的 traceback 和 getinfo 函数, getinfo 函数用于返回函数信息的表。

另一个实例

我们经常需要调试函数的内的局部变量。我们可以使用 getupvalue 函数来设置这些局部变量。实例如下:

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

在以上实例中,计数器在每次调用时都会自增1。实例中我们使用了 getupvalue 函数查看局部变量的当前状态。我们可以设置局部变量为新值。实例中,在设置前 n 的值为 2,使用 setupvalue 函数将其设置为 10。现在我们调用函数,执行后输出为 11 而不是 3。

调试类型

  • 命令行调试
  • 图形界面调试

命令行调试器有:RemDebug、clidebugger、ctrace、xdbLua、LuaInterface - Debugger、Rldb、ModDebug。

图形界调试器有:SciTE、Decoda、ZeroBrane Studio、akdebugger、luaedit。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容

  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,674评论 0 38
  • Lua 提供了 debug 库用于提供创建我们自定义调速器的功能。Lua 本身并未有内置的调速器,但很多开发者共享...
    谁说我是小小云阅读 3,106评论 0 0
  • 第一篇 语言 第0章 序言 Lua仅让你用少量的代码解决关键问题。 Lua所提供的机制是C不擅长的:高级语言,动态...
    testfor阅读 2,632评论 1 7
  • 你们明明彼此相爱着; 你们明明彼此生命交织在一起,你的家人也是他的家人,他的家人也是你的亲人; 你们明明彼此担心,...
    点点点儿大阅读 228评论 0 0
  • 如果有那样的选择摆在你面前,你会成为简·奥斯汀吗? 我听过很多女孩子说想要成为Jane,但,大都是不够深刻地了解这...
    Only怡欢阅读 972评论 0 9