lua debug相关方法详解

lua debug相关方法详解

  • 1. debug.debug()
  • 2. debug.getinfo(func | level [, what])
  • 3. debug.getlocal(func-or-level, localindex)
  • 4. debug.setlocal(level, local_number, value)
  • 5. debug.getupvalue(func, upvalue_index)
  • 6. debug.setupvalue(func, upvalue_index, value)
  • 7. debug.traceback([thread,] [message [, level]])
  • 8. debug.sethook(func, mask [, count])
  • 9. debug.getregistry()
  • 10. debug.getmetatable(object)
  • 11. debug.setmetatable(object, metatable)
  • 12. debug.upvalueid(f, n)
  • 13. debug.upvaluejoin(f1, n1, f2, n2)

在 Lua 中,debug 库提供了一组强大的函数,用于调试和跟踪代码的执行,这些函数可用于查看堆栈信息、检查运行时状态、设置钩子等

1. debug.debug()

该函数在交互模式下进入调试器,允许用户逐步执行代码

local function test()local a = 10local b = 20print(a + b)
endtest()
debug.debug()  -- 触发调试器

执行 debug.debug() 将转到调试模式

2. debug.getinfo(func | level [, what])

此函数返回指定函数或调用的当前状态信息,level 是调用堆栈的深度,what 用于指定返回的信息类型(默认值为"flnSu"),第一个参数可以是一个函数或一个整数,如果是函数,debug.getinfo返回关于该函数的信息,如果是整数,表示调用栈的层级

what 参数可以是:

  • f:返回函数对象
  • n:返回函数的名称
  • l:返回当前执行的行号
  • S:返回源代码文件名和行号
  • L:返回当前函数的所有行号范围
  • u:返回函数的未使用参数的数量
  • t:返回函数类型(C 函数或 Lua 函数)
  • g:返回生成器的上下文

debug.getinfo 返回一个包含调试信息的表,表中可能包含以下字段:

  • name:函数的名称
  • namewhat:函数名称的类型,可以是 “global”, “local”, “field”, “method” 或 “”
  • func:函数对象
  • source:源代码文件名(以 @ 开头表示文件,以 = 开头表示匿名函数)
  • short_src:源代码文件的简短名称
  • linedefined:函数定义的起始行号
  • lastlinedefined:函数定义的结束行号
  • currentline:当前执行的行号
  • nups:函数的上值数量
  • nparams:函数的参数数量
  • isvararg:函数是否是可变参数函数
  • istailcall:当前是否是尾调用
  • isC:函数是否是 C 函数
  • isyieldable:函数是否可以挂起
local function sample()return 42
endlocal info = debug.getinfo(sample)
print(info.source)  -- 打印函数的源代码路径
print(info.linedefined)  -- 打印函数开始的行号

3. debug.getlocal(func-or-level, localindex)

返回指定级别的本地变量的值

  • func-or-level:
    • 可以是一个函数,表示要获取局部变量的函数
    • 也可以是一个整数,表示调用栈的层级,1 表示当前函数,2 表示调用当前函数的函数,依此类推
  • localindex:
    • 局部变量的索引,从 1 开始,可以使用负数来表示从最后一个局部变量开始计数
  • 返回值:
    • 局部变量的值
    • 如果变量不存在,返回 nil

获取当前函数的局部变量:

function test()local a = 10local b = 20local name, value = debug.getlocal(1, 1)  -- 获取第一个局部变量print("Variable name value:", name, value)
endtest()

获取调用栈中上一层函数的局部变量:

function outer()local x = 100inner()
endfunction inner()local name, value = debug.getlocal(2, 1)  -- 获取外层函数的第一个局部变量print("Outer variable name value:", name, value)
endouter()

注意事项

  • debug.getlocal 返回的表包含变量的名称和值
  • 使用负数索引时,-1 表示最后一个局部变量,-2 表示倒数第二个,依此类推
  • 如果函数没有局部变量,或者指定的索引超出范围,返回 nil

4. debug.setlocal(level, local_number, value)

设置指定级别的本地变量的值

local function bar()local x = 10local y = 20debug.setlocal(1, 1, 30)  -- 将第一个本地变量的值设置为 30print(x)  -- 输出 30
endbar()

5. debug.getupvalue(func, upvalue_index)

该函数用于获取函数的上值(upvalue)信息,上值是 Lua 中函数闭包的概念,允许函数访问其定义环境中的局部变量,通过debug.getupvalue可查看函数的上值名称和对应的值

local function outer()local x = 10local y = 11local function inner()return x, yendreturn inner
endlocal inner = outer()
local name1, value1 = debug.getupvalue(inner, 1)  -- 获取上值的值
local name2, value2 = debug.getupvalue(inner, 1)  -- 获取上值的值
print(name1, value1, name2, value2)  -- 输出 x 10 y 11

6. debug.setupvalue(func, upvalue_index, value)

设置指定函数的上值

local function outer()local x = 10local function inner()return xendreturn inner
endlocal inner = outer()
debug.setupvalue(inner, 1, 20)  -- 修改上值
print(inner())  -- 输出 20

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

返回当前堆栈的完整调用回溯,通常用于错误处理

local function causeError()error("An error occurred!")
endlocal function errorHandler()local message = debug.traceback("", 2)print("Error stack trace:\n" .. message)
endxpcall(causeError, errorHandler)

8. debug.sethook(func, mask [, count])

设置一个钩子函数,可使程序在每次调用或返回时执行指定的函数

hook, mask, count = debug.sethook([function [, mask [, count]]])
  • function:
    • 钩子函数,当满足特定条件时会被调用
    • 如果设置为 nil,则取消当前的调试钩子
  • mask: 控制钩子的触发条件,可以是以下值的任意组合:
    • ‘c’: 每次调用
    • ‘r’: 每次返回
    • ‘l’: 每行代码执行时
    • “count”:每隔 count 次执行调用钩子函数
  • count(可选):
    • 仅当 mask 包含"count" 时有效,指定每隔多少次执行调用钩子函数
local function hook()print("A line was executed!")
enddebug.sethook(hook, "l")  -- 每次执行一行代码时调用 hooklocal function sampleFunction()print("Inside sample function.")
endsampleFunction()
debug.sethook()  -- 取消钩子

9. debug.getregistry()

返回注册表(registry)表,Lua 使用这个表来存储全局数据

local registry = debug.getregistry()
print(registry)  -- 输出注册表的内容

10. debug.getmetatable(object)

获取指定对象的元表(metatable)

local t = {}
local mt = { __index = function(t, k) return k end }
setmetatable(t, mt)local meta = debug.getmetatable(t)
print(meta)  -- 输出元表

与getmetatable主要区别

  1. 权限检查:
  • getmetatable 会尊重 __metatable 字段的设置,如果 __metatable 为 nil,则返回 nil;如果 __metatable 为其他值,则返回该值
  • debug.getmetatable 忽略 __metatable 字段的设置,总是返回对象的实际元表
  1. 使用场景:
  • 标准用途:如果只是想获取对象的元表,并且尊重 __metatable 字段的保护机制,使用 getmetatable
  • 调试用途:如果需要绕过 __metatable 的保护机制,获取对象的实际元表,使用 debug.getmetatable
  1. 安全性:
  • getmetatable 更安全,因为它尊重 __metatable 字段的设置,可以防止未经授权的访问和修改
  • debug.getmetatable 由于可以绕过保护机制,使用时需要特别小心,以免破坏程序的正常运行

11. debug.setmetatable(object, metatable)

设置指定对象的元表

local t = {}
local mt = { __index = function(t, k) return k end }
debug.setmetatable(t, mt)print(getmetatable(t))  -- 输出新的元表

与setmetatable主要区别

  1. 权限检查:
  • setmetatable 会尊重 __metatable 字段的保护机制,如果元表被保护,则无法修改,会抛出错误
  • debug.setmetatable 无视 __metatable 字段的保护机制,可以强制修改元表
  1. 使用场景:
  • 标准用途:如果只是想设置或修改对象的元表,并且尊重 __metatable 字段的保护机制,使用 setmetatable
  • 调试用途:如果需要绕过 __metatable 的保护机制,强制修改对象的元表,使用 debug.setmetatable
  1. 安全性:
  • setmetatable 更安全,因为它尊重 __metatable 字段的保护机制,可以防止未经授权的修改
  • debug.setmetatable 由于可以绕过保护机制,使用时需要特别小心,以免破坏程序的正常运行
  1. 返回值:
  • setmetatable 返回设置元表后的对象,可以用于链式操作
  • debug.setmetatable 没有返回值

12. debug.upvalueid(f, n)

返回指定函数第 n 个上值的唯一标识符, 可以用来判断两个函数引用的 upvalue 是否是同一个值

local function outer()local x = 10local function inner()return xendreturn inner
endlocal inner = outer()
local upvalueId = debug.upvalueid(inner, 1)
print(upvalueId)  -- 输出上值的唯一标识符

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

将两个函数的第 n1 和 n2 个上值关联起来,可将一个闭包的上值连接到另一个闭包的上值,以实现上值的共享

使用场景

  1. 共享状态:当需要多个闭包共享同一个变量时,可以通过 debug.upvaluejoin 来实现
  2. 调试和测试:在调试过程中,可能需要修改闭包的上值,以观察不同的行为
  3. 高级编程技巧:在某些高级编程技巧中,可能需要手动管理闭包的上值
-- 定义两个闭包,每个闭包有一个上值
local function closure1()local x = 10return function() return x end
endlocal function closure2()local y = 20return function() return y end
end-- 创建两个闭包实例
local func1 = closure1()
local func2 = closure2()-- 获取上值的索引
local up1_name, up1_value = debug.getupvalue(func1, 1)
local up2_name, up2_value = debug.getupvalue(func2, 1)-- 连接上值
debug.upvaluejoin(func1, 1, func2, 1)print(func1())  --> 输出20 是closure2的上值,触发了共享值

注意事项

  1. 风险:不正确的使用 debug.upvaluejoin 可能会导致程序行为不可预测,因此在使用时需要非常小心
  2. 性能:频繁地操作上值可能会影响性能,应尽量避免在性能敏感的代码中使用
  3. 可维护性:过度使用调试函数可能降低代码的可读性和可维护性,应尽量在必要时使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/64150.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《计算机网络(第7版)-谢希仁》期末考试复习题和答案(总结整理)

目录 前言: 一、选择题。 二、填空题。 三、名词解释。 四、简答题。 前言: 这个自动标题自己带了序号,一开始想全部选项和题号都改过来的,结果一看一百多个全是,懒得改了 一、选择题。 1、广域网覆盖的地理范围…

【再谈设计模式】享元模式~对象共享的优化妙手

一、引言 在软件开发过程中,我们常常面临着创建大量细粒度对象的情况,这可能会导致内存占用过高、性能下降等问题。享元模式(Flyweight Pattern)就像是一位空间管理大师,它能够在不影响功能的前提下,有效地…

Milvus×EasyAi:如何用java从零搭建人脸识别应用

如何从零搭建一个人脸识别应用?不妨试试原生Java人工智能算法:EasyAi Milvus 的组合拳。 本文将使用到的软件和工具包括: EasyAi:人脸特征向量提取Milvus:向量数据库用于高效存储和检索数据。 01. EasyAi:…

NS3学习——tcpVegas算法代码详解(2)

NS3学习——tcpVegas算法代码详解(1)-CSDN博客 目录 4.TcpVegas类中成员函数 (5) CongestionStateSet函数 (6) IncreaseWindow函数 1.检查是否启用 Vgas 2.判断是否完成了一个“Vegas 周期” 2.1--if:判断RTT样本数量是否足够 2.2--e…

GitLab 将停止为中国区用户提供服务,60天迁移期如何应对? | LeetTalk Daily

“LeetTalk Daily”,每日科技前沿,由LeetTools AI精心筛选,为您带来最新鲜、最具洞察力的科技新闻。 GitLab作为一个广受欢迎的开源代码托管平台,近期宣布将停止服务中国大陆、澳门和香港地区的用户提供服务。根据官方通知&#x…

华为实训课笔记 2024 1223-1224

华为实训 12/2312/24 12/23 [Huawei]stp enable --开启STP display stp brief --查询STP MSTID Port Role STP State Protection 实例ID 端口 端口角色 端口状态 是否开启保护[Huawei]display stp vlan xxxx --查询制定vlan的生成树计算结…

企业数字化转型中如何区分“IT投入”和“业务投入”

在数字化转型的浪潮中,企业往往面临一个关键问题:如何区分“IT投入”和“业务投入”?在很多企业中,这两个概念往往被混淆,不少公司甚至认为“数字化转型”就是“IT的事情”,但实际上,它们之间有…

【Spring AI】Spring AI Alibaba的简单使用

提示:文章最后有详细的参考文档。 前提条件 SpringBoot版本为3.x以上JDK为17以上申请api-key,地址:百炼平台 引入依赖 说明:我的springboot版本为3.2.4,spring-ai-alibaba-starter版本为1.0.0-M2.1(对应spring-ai版本…

《Java源力物语》-3.空值猎手

~犬📰余~ “我欲贱而贵,愚而智,贫而富,可乎? 曰:其唯学乎” \quad 夜色渐深,在一处偏僻小径上,月光透过浓密的源力云层,在地面上投下斑驳的光影。String正独自练习着刚从…

科技云报到:人工智能时代“三大件”:生成式AI、数据、云服务

科技云报到原创。 就像自行车、手表和缝纫机是工业时代的“三大件”。生成式AI、数据、云服务正在成为智能时代的“新三大件”。加之全球人工智能新基建加速建设,成为了人类社会数字化迁徙的助推剂,让新三大件之间的耦合越来越紧密。从物理世界到数字世…

hiprint结合vue2项目实现静默打印详细使用步骤

代码地址是:vue-plugin-hiprint: hiprint for Vue2/Vue3 ⚡打印、打印设计、可视化设计器、报表设计、元素编辑、可视化打印编辑 本地安装包地址:electron-hiprint 发行版 - Gitee.com 1、先安装hipint安装包在本地 2、项目运行npm(socket.…

CUDA各种内存和使用方法

文章目录 1、全局内存2、局部内存3、共享内存3.1 静态共享内存3.2 动态共享内存 4、纹理内存5、常量内存6、寄存器内存7、用CUDA运行时API函数查询设备CUDA 错误检测 1、全局内存 特点:容量最大,访问延时最大,所有线程都可以访问。 线性内存…

Chapter 03 复合数据类型-1

1.列表 Python内置的一种有序、可变的序列数据类型; 列表的定义: [ ]括起来的逗号分隔的多个元素组成的序列 列表对象的创建: (1)直接赋值 >>> list1 []#创建一个空列表赋值给list1 >>> list…

【后端】LNMP环境搭建

长期更新各种好文,建议关注收藏! 本文近期更新完毕。 LNMPlinuxnginxmysqlphp 需要的资源 linux服务器 web服务软件nginx 对应的语言编译器代码文件 数据库mysql安装 tar.gz包或者命令行安装 进入root: sodu 或su mkdir path/{server,soft}…

基于PyQt5的UI界面开发——多界面切换

介绍 最初,因为课设的缘故,我只是想做一个通过按键进行切面切换而已,但是我看网上资料里面仅是语焉不详,让我困惑的很,但后面我通过摸索才发现这件事实在是太简单了,因此我想要记录下来。 本博客将介绍如…

操作002:HelloWorld

文章目录 操作002:HelloWorld一、目标二、具体操作1、创建Java工程①消息发送端(生产者)②消息接收端(消费者)③添加依赖 2、发送消息①Java代码②查看效果 3、接收消息①Java代码②控制台打印③查看后台管理界面 操作…

机器视觉检测相机基础知识 | 颜色 | 光源 | 镜头 | 分辨率 / 精度 / 公差

注:本文为 “keyence 视觉沙龙中机器视觉检测基础知识” 文章合辑。 机器视觉检测基础知识(一)颜色篇 视觉检测硬件构成的基本部分包括:处理器、相机、镜头、光源。 其中,和光源相关的最重要的两个参数就是光源颜色和…

【每日学点鸿蒙知识】压力测试、Web组件拦截器、nfc开关状态、定位能力、rn支持的三方库

1、HarmonyOS的wukong 支持运行python脚本进行压力或者常规测试吗? Python脚本调用hdc命令,执行hdc shell wukong XXXwukong只支持稳定性压测,普通测试建议使用arkxtest测试框架 2、Web组件页面内跳转时自定义WebHeader问题? 如…

GDPU Vue前端框架开发 期末赛道出勇士篇(更新ing)

记住,年底陪你跨年的不会仅是方便面跟你的闺蜜,还有孑的笔记。 选择题 1.下列选项用于设置Vue.js页面视图的元素是()。 A. Template B. script C. style D. title 2.下列选项中能够定义Vuejs根实例对象的元素是(&…

Flutter开发HarmonyOS 鸿蒙App的好处、能力以及把Flutter项目打包成鸿蒙应用

Flutter开发HarmonyOS的好处: Flutter是谷歌公司开发的一款开源、免费的UI框架,可以让我们快速的在Android和iOS上构建高质量App。它最大的特点就是跨平台、以及高性能。 目前 Flutter 已经支持 iOS、Android、Web、Windows、macOS、Linux 的跨平台开发…