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.pswp.cn/web/64150.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/64150.shtml
英文地址,請注明出處:http://en.pswp.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 的跨平臺開發…