使用lua實現try-catch異常捕獲
lua原生並沒有提供try-catch的語法來捕獲異常處理,但是提供了pcall/xpcall
等介面,可在保護模式下執行lua函式。
因此,可以通過封裝這兩個介面,來實現try-catch塊的捕獲機制。
我們可以先來看下,封裝後的try-catch使用方式:
try
{
-- try 程式碼塊
function ()
error("error message")
end,
-- catch 程式碼塊
catch
{
-- 發生異常後,被執行
function (errors)
print (errors)
end
}
}
上面的程式碼中,在try塊內部認為引發了一個異常,並且丟擲錯誤訊息,在catch中進行了捕獲,並且將錯誤訊息進行輸出顯示。
這裡除了對pcall/xpcall
進行了封裝,用來捕獲異常資訊,還利用了lua的函式呼叫語法特性,在只有一個引數傳遞的情況下,lua可以直接傳遞一個table型別,並且省略()
其實try後面的整個{...}
都是一個table而已,作為引數傳遞給了try函式,其具體實現如下:
function try(block)
-- get the try function
local try = block[1 ]
assert(try)
-- get catch and finally functions
local funcs = block[2]
if funcs and block[3] then
table.join2(funcs, block[2])
end
-- try to call it
local ok, errors = pcall(try)
if not ok then
-- run the catch function
if funcs and funcs.catch then
funcs.catch(errors)
end
end
-- run the finally function
if funcs and funcs.finally then
funcs.finally(ok, errors)
end
-- ok?
if ok then
return errors
end
end
可以看到這裡用了pcall
來實際呼叫try塊裡面的函式,這樣就算函式內部出現異常,也不會中斷程式,pcall
會返回false表示執行失敗
並且返回實際的出錯資訊,如果想要自定義格式化錯誤資訊,可以通過呼叫xpcall來替換pcall,這個介面與pcall相比,多了個錯誤處理函式:
local ok, errors = xpcall(try, debug.traceback)
你可以直接傳入debug.traceback
,使用預設的traceback處理介面,也可以自定義一個處理函式:
-- traceback
function my_traceback(errors)
-- make results
local level = 2
while true do
-- get debug info
local info = debug.getinfo(level, "Sln")
-- end?
if not info or (info.name and info.name == "xpcall") then
break
end
-- function?
if info.what == "C" then
results = results .. string.format(" [C]: in function '%s'\n", info.name)
elseif info.name then
results = results .. string.format(" [%s:%d]: in function '%s'\n", info.short_src, info.currentline, info.name)
elseif info.what == "main" then
results = results .. string.format(" [%s:%d]: in main chunk\n", info.short_src, info.currentline)
break
else
results = results .. string.format(" [%s:%d]:\n", info.short_src, info.currentline)
end
-- next
level = level + 1
end
-- ok?
return results
end
-- 呼叫自定義traceback函式
local ok, errors = xpcall(try, my_traceback)
回到try-catch上來,通過上面的實現,會發現裡面其實還有個finally的處理,這個的作用是對於try{}
程式碼塊,不管是否執行成功,都會執行到finally塊中
也就說,其實上面的實現,完整的支援語法是:try-catch-finally
模式,其中catch和finally都是可選的,根據自己的實際需求提供
例如:
try
{
-- try 程式碼塊
function ()
error("error message")
end,
-- catch 程式碼塊
catch
{
-- 發生異常後,被執行
function (errors)
print(errors)
end
},
-- finally 程式碼塊
finally
{
-- 最後都會執行到這裡
function (ok, errors)
-- 如果try{}中存在異常,ok為true,errors為錯誤資訊,否則為false,errors為try中的返回值
end
}
}
或者只有finally塊:
try
{
-- try 程式碼塊
function ()
return "info"
end,
-- finally 程式碼塊
finally
{
-- 由於此try程式碼沒發生異常,因此ok為true,errors為返回值: "info"
function (ok, errors)
end
}
}
處理可以在finally中獲取try裡面的正常返回值,其實在僅有try的情況下,也是可以獲取返回值的:
-- 如果沒發生異常,result 為返回值:"xxxx",否則為nil
local result = try
{
function ()
return "xxxx"
end
}
可以看到,這個基於pcall的try-catch-finally
異常捕獲封裝,使用上還是非常靈活的,而且其實現相當的簡單
這也充分說明了lua是一門已非常強大靈活,又非常精簡的語言。
在xmake的自定義指令碼、外掛開發中,也是完全基於此異常捕獲機制
這樣使得擴充套件指令碼的開發非常的精簡可讀,省去了繁瑣的if err ~= nil then
返回值判斷,在發生錯誤時,xmake會直接丟擲異常進行中斷,然後高亮提示詳細的錯誤資訊。
例如:
target("test")
set_kind("binary")
add_files("src/*.c")
-- 在編譯完ios程式後,對目標程式進行ldid簽名
after_build(function (target))
os.run("ldid -S %s", target:targetfile())
end
只需要一行os.run
就行了,也不需要返回值判斷是否執行成功,因為執行失敗後,xmake會自動拋異常,中斷程式並且提示錯誤
如果你想在執行失敗後,不直接中斷xmake,繼續往下執行,可以自己加個try快就行了:
target("test")
set_kind("binary")
add_files("src/*.c")
after_build(function (target))
try
{
function ()
os.run("ldid -S %s", target:targetfile())
end
}
end
如果還想捕獲出錯資訊,可以再加個catch:
target("test")
set_kind("binary")
add_files("src/*.c")
after_build(function (target))
try
{
function ()
os.run("ldid -S %s", target:targetfile())
end,
catch
{
function (errors)
print(errors)
end
}
}
end
不過一般情況下,在xmake中寫自定義指令碼,是不需要手動加try-catch的,直接呼叫各種api,出錯後讓xmake預設的處理程式接管,直接中斷就行了。。
最後附上try-catch-finally
實現的相關完整原始碼:
相關推薦
使用lua實現try-catch異常捕獲
lua原生並沒有提供try-catch的語法來捕獲異常處理,但是提供了pcall/xpcall等介面,可在保護模式下執行lua函式。 因此,可以通過封裝這兩個介面,來實現try-catch塊的捕獲機制。 我們可以先來看下,封裝後的try-catch使用方式:
.net try catch 異常捕獲的正確使用姿勢。。
很慚愧,寫了好多年的程式碼, 最基本的try catch 才剛剛會正確的使用, 以前只能說叫會用, 但是用法不正確。 先說說,異常的3種使用方式。 見下面的程式碼。 public static int Method1() {
javascript中的try catch異常捕獲機制
1.跟java一樣,javascript也具有try catch塊,進行異常捕獲的機制。 (1)典型的try cat
php中為什麼要用try catch來捕獲異常
Try - 使用異常的函式應該位於 "try" 程式碼塊內。如果沒有觸發異常,則程式碼將照常繼續執行。但是如果異常被觸發,會丟擲一個異常。 Catch - "catch" 程式碼塊會捕獲異常,並建立一個包含異常資訊的物件。 讓我們觸發一個異常: //建立可丟擲一個異常的函式 function che
多此一舉, C實現 try-catch
trycatch 線程安全 C 異常處理 在做NtyTcp的時候,有一些,就想用c來實現一套try-catch異常處理子系統。不討論C語言本身為什麽不加try-catch,每個開發的朋友對於這個問題,都能說出一大堆的理由。其實我也是不太喜歡強行在c中加入一個try-catch。就像把try-c
try catch 異常處理
學習code: int main(int argc, char* argv[])...{ try...{... ... } catch(std::exception& e) ...{ std::cerr <<"Exception caught
try catch異常丟擲與spring事務回滾策略相關
將異常捕獲,並且在catch塊中不對事務做顯式提交(或其他應該做的操作如關閉資源等)=生吞掉異常; spring的事務邊界是在呼叫業務方法之前開始的,業務方法執行完畢之後來執行commit or rollback(Spring預設取決於是否丟擲runtime異常).
SQL Server Try Catch 異常捕捉
背景 今天遇到一個關於try catch 使用比較有意思的問題。如下一段程式碼: SELECT @@TRANCOUNT AS A BEGIN TRY BEGIN TRAN SELECT @@TRANCO
C語言實現try catch處理
我們都知道,在Java、C#等高階程式語言中,都自帶有異常處理機制,其基本結構如下: try{ 程式語句; }catch(Exception ex){ 異常處理; } 這樣做不但可以防止程式異常終止,而且在出現錯誤時可以及時作一些釋放資源處理,對程式能繼續健壯的執行下去尤
C# .net程式設計基礎-try-catch異常處理-階乘示例
在軟體開發過程中,程式異常是十分常見的,也就是我們常說的BUG,因此需要我們對不可預期的異常進行處理。 異常處理其實很簡單,最開始我也就得很難,不用怕、真的挺簡單的,真正理解了頂多也就一個try-catch語句和throw語句。 try-catch語
Thinkphp try{}catch()異常處理的寫法
最近在專案開發中 異常處理捕獲不到,查了下關於異常處理的資料,還是名稱空間的問題 public function del ($id) {//在模型中丟擲異常 if ( !$id || !is_array($id) ) { E('ID不合
try...catch異常處理使用注意——包含程式碼過多
Java中使用try…catch來處理異常,今天在debug一段用try..catch處理的程式碼段,除錯時throws Exception, 感覺丟擲的異常有問題,但是又很難對出現問題的地方進行識別定
spring的註解事務與try catch 異常處理
Spring的預設事務機制,當出現unchecked異常時候回滾,checked異常的時候不會回滾; 異常中unchecked異常包括error和runtime異常,需要try catch或向上丟擲的異常為checked異常比如IOException,也就是說程式丟擲r
try catch異常的一些注意的地方
網上的一些總結記錄:1 try、catch、finally語句中,在如果try語句有return語句,則返回的之後當前try中變數此時對應的值,此後對變數做任何的修改,都不影響try中return的返回值2 如果finally塊中有return 語句,則返回try或catch
Java異常捕獲之一道try-catch-finally語句題
span pri div system 處理機 out nal exception for 今天,學習了try-catch-finally語句,本來覺得蠻簡單、易懂的。搜了一道相關類型的題。結果信心被潑了盆冷水。先把題Mark一下,出去透透風。 1 public cla
PHP 使用try catch,捕獲異常
get type 設置 html 異常信息 utf-8 tex http mes <?php header(‘Content-type:text/html;charset=utf-8‘); $a = 1; $b = 2; try {
try catch 小結 , node的回調callback裏不能捕獲異常 , 不能被v8優化(現在能了),
容易 sin ejs called ack tro 崩潰 span 檢查 《深入淺出Nodejs》時,在第四章 - 異步編程中作者樸靈曾提到,異步編程的難點之一是異常處理,書中描述"嘗試對異步方法進行try/catch操作只能捕獲當次事件循環內的異常,對call back執
spring 聲明式事務中try catch捕獲異常
調用 color exception 代碼 狀態 新的 for 自定義 這樣的 原文:http://heroliuxun.iteye.com/blog/848122 今天遇到了一個這個問題 最近遇到這樣的問題,使用spring時,在業務層需要捕獲異常(特殊需要),當前一般
js中的異常捕獲 try{} catch{}(二)
事件輪循中,丟擲的異常資訊會丟失函式呼叫的路徑,所以每一步都要進行錯誤處理 function a(){ b(); } function b(){ c(); } function c(){ // setTimeout(() => { // throw new
在try catch中開啟新的執行緒,不能捕獲執行緒裡面的異常
近期在review程式碼的時候發現,有些人為了圖方便,直接在程式碼引用的最外層放上一個try catch,以為可以捕獲一切異常,降低崩潰率。 事實上,如果try的是新開啟的一個執行緒,那麼這個執行緒裡面出現的異常是catch不到。也就是說在A執行緒中new B執行緒,B執行緒中出現的cr