Luaのdebug.traceback
6628 ワード
新しいtraceback:
分析:
Debugライブラリの重要なアイデアの一つはスタックレベルです.スタック・レベルは、現在の時点でアクティブな特殊な関数を指す数値です.つまり、この関数は呼び出されていますが、まだ返されていません.呼び出しdebugライブラリの関数レベルは1であり、呼び出した関数レベルは2である.23.1自省(Introspective)デバグライブラリにおける主な自省関数はデバグである.getinfo.彼の最初のパラメータは、関数またはスタックレベルであってもよい.関数fooに対してdebugを呼び出す.getinfo(foo)は、この関数情報に関するテーブルを返します.この表には、関数が定義されている場所を示すドメインがあります.関数が1つの文字列内で定義されている場合(loadstringによって)、sourceはその文字列です.関数が1つのファイルで定義されている場合、sourceは@にファイル名を付けます.ü short_src、sourceの短いバージョン(最大60文字)で、役に立つエラー情報を記録します.ülinedefined、sourceで関数が定義されている行番号.üwhat、関数タイプを明記します.fooが通常のLua関数であれば、結果は「Lua」である.C関数の場合、結果は「C」です.Luaのメインchunkであれば「main」となります.üname、関数の適切な名前.ünamewhat、前のフィールドが表す意味.このフィールドの値は、W「global」、「local」、「method」、「field」、または「」(空の文字列)です.空の文字列は、Luaがこの関数名を見つけていないことを意味します.ünups、関数のupvaluesの個数.üfunc、関数自体;詳細は後を見る.fooがC関数である場合,Luaは多くの関連情報を知ることができないため,what,name,namewhatのいくつかのドメインの値しか利用できない.数字nでdebugを呼び出す.getinfo(n)の場合、nレベルスタックのアクティブ関数の情報データが返されます.例えば、n=1の場合、呼び出し中の関数の情報が返される.(n=0はC関数getinfoそのものを表す)nがスタック内のアクティブ関数の個数より大きい場合debug.getinfoはnilを返します.数字nを使用してdebugを呼び出すとgetinfoがアクティブ関数の情報をクエリーすると、返される結果tableにはcurrentline、すなわちその時点で関数が存在する行番号という追加のドメインがあります.またfuncはn級を指定するアクティビティ関数を表す.フィールド名の書き方にはいくつかのテクニックがあります.覚えておいてください:Luaでは関数が第1クラスの値であるため、1つの関数に複数の関数名がある可能性があります.指定した値の関数を検索すると、Luaはまずグローバル変数で検索し、見つからない場合はこの関数を呼び出すコードでどのように呼び出されているかを見ます.この場合、getinfoを数値呼び出しで呼び出す場合にのみ機能します.つまり、呼び出しに関する詳細を取得できます.関数getinfoの効率は高くありません.Luaは、プログラム実行を弱めずにdebug情報(Lua keeps debug information in a form that does not impair program execution)を保存し、効率を2位に置く.パフォーマンスをよりよく実行するために、getinfoオプションの2番目のパラメータを使用して、どの情報を選択するかを指定できます.このパラメータを指定すると、プログラムはユーザーが関心を持っていない情報を収集するのに時間を無駄にしません.このパラメータのフォーマットは文字列で、各文字はタイプの情報を表し、使用可能な文字の意味は以下の通りです:'n'selects fields name and namewhat'f'selects field func'S'selects fields source,short_src,what,and linedefined'l'selects field currentline'u'selects field nupの下の関数はdebugを明らかにした.getinfoの使用、関数印刷アクティブスタックの元の追跡情報(traceback):function traceback()local level=1 while true do local info=debug.getinfo(level, "Sl") if not info then break end if info.what == "C"then -- is a C function? print(level,"C function")else--a Lua function print(string.format("%s":%d",info.short_src,info.currentline))end level=level+1 end end endはこの関数を改善することが難しくなく、getinfoがより多くのデータを取得するようにし、実際にdebugライブラリは改善されたバージョンdebugを提供している.traceback、私たちの上の関数とは違います.debug.tracebackは結果を印刷するのではなく、文字列を返します.23.1.1ローカル変数呼び出しdebugライブラリのgetlocal関数にアクセスすると、アクティブなローカル変数にアクセスできます.この関数は、クエリーする関数のスタックレベルと変数のインデックスの2つのパラメータから構成されます.関数には、変数名と変数の現在値の2つの戻り値があります.指定した変数のインデックスがアクティブな変数の数より大きい場合、getlocalはnilを返します.指定したスタックレベルが無効な場合、関数はエラーを放出します.(debug.getinfoを使用してスタックレベルの有効性を確認できます)Luaは、関数に表示されるすべてのローカル変数を順次カウントし、現在の関数の範囲内で有効なローカル変数である場合にのみカウントします.例えば、次のコードfunction foo(a,b)local x do local c=a-b end local a=1 while true do local name,value=debug.getlocal(1,a)if not name then break end print(name,value)a=a+1 end end foo(10,20)の結果,a 10 b 20 x nil a 4インデックスが1の変数はa,2はb,3はx,4は別のaであった.getlocalが呼び出された点で、cは範囲を超えており、nameもvalueも範囲内ではありません.(ローカル変数は初期化後にのみ表示されることを覚えておいてください)debugも使用できます.setlocalはローカル変数の値を変更します.彼の最初の2つのパラメータはスタックレベルと変数インデックスで、3番目のパラメータは変数の新しい値です.この関数は、変数名またはnil(変数インデックスが範囲外の場合)23.1.2を返します.Upvaluesにアクセスするには、debugライブラリのgetupvalue関数からLua関数のupvaluesにアクセスすることもできます.局所変数とは異なり,関数がアクティブでなくてもupvaluesがある(これが閉パケットの意味である).したがって、getupvalueの最初のパラメータはスタックレベルではなく関数(正確には閉パケット)であり、2番目のパラメータはupvalueのインデックスである.Luaはupvalueが1つの関数で参照される順序で順次番号付けされ、1つの関数に同じ名前のupvaluesが2つあることはできないため、この順序はupvalueとはあまり関連がない(relevant).関数ebugを使用できます.setupvalue upvaluesを変更します.彼には3つのパラメータがあるかもしれません.1つの閉パッケージ、1つのupvaluesインデックス、新しいupvalue値です.setlocalと同様に、この関数はupvalueの名前、またはnil(upvalueインデックスがインデックス範囲を超えている場合)を返します.次のコードは、変数名が与えられた場合に、呼び出されている関数の任意の変数の値にアクセスする方法を示します:function getvarvalue(name)local value,found--try local variables local i=1 while true do local n,v=debug.getlocal(2, i) if not n then break end if n == name then value = v found = true end i = i + 1 end if found then return value end -- try upvalues local func = debug.getinfo(2).func i = 1 while true do local n, v = debug.getupvalue(func, i) if not n then break end if n == name then return v end i = i + 1 end -- not found; get global return getfenv(func)[name]endまず、この変数がローカル変数であるかどうかを試します.与えられた名前の変数に複数の変数がある場合は、最高インデックスを持つものにアクセスする必要があります.そのため、ループ全体を巡回する必要があります.ローカル変数に指定した名前の変数が見つからない場合は、upvaluesであるかどうかを試します.まずdebugを使用します.getinfo(2).funcは呼び出した関数を取得し、この関数のupvaluesを巡り、最後に所定の名前の変数を見つけたら、グローバル変数で検索します.注意debugを呼び出す.getlocalとdebug.getinfoのパラメータ2(呼び出し中の関数にアクセスするために使用される)の使い方.
local function toStringEx(v , len)
if len == nil then
len = 0;
end
local pre = string.rep('\t',len);
local ret = "";
if type(v) == "table" then
if len > 5 then
return "\t{ ... }";
end
local t = "";
for k,v1 in pairs(v) do
t = t .. "
\t" .. pre .. tostring(k) .. ":";
t = t .. tostring(v1 , len + 1);
end
if t == "" then
ret = ret .. pre .. "{ }\t{" .. tostring(v) .. "}";
else
if len > 0 then
ret = ret .. "\t{" .. tostring(v) .. "}
";
end
ret = ret .. pre .. "{" .. t .. "
" .. pre .."}";
end
else
ret = ret .. pre .. tostring(v) .. "\t{" .. type(v) .. "}";
end
return ret;
end
local function tracebackex(baseLevel)
local ret = "";
local level = baseLevel;
ret = ret .. "stack traceback:
";
while true do
local info = debug.getinfo(level,"Sln");
if not info then
break ;
end
if info.what == "C" then
ret = ret .. tostring(level - baseLevel + 1) .. "\tC function " ..info.name .. "
";
else
ret = ret .. tostring(level - baseLevel + 1) .. string.format("\t[string \"%s\"]:%d in function %s
",info.source,info.currentline,info.name or info.what);
end
-- local i = 1;
-- while true do
-- local name , value = debug.getlocal(level,i);
-- if not name then
-- break;
-- end
-- ret = ret .. "\t\t" .. name .. " =\t" .. toStringEx(value , 3) .. "
";
-- i = i + 1;
-- end
level = level + 1;
end
return ret;
end
分析:
Debugライブラリの重要なアイデアの一つはスタックレベルです.スタック・レベルは、現在の時点でアクティブな特殊な関数を指す数値です.つまり、この関数は呼び出されていますが、まだ返されていません.呼び出しdebugライブラリの関数レベルは1であり、呼び出した関数レベルは2である.23.1自省(Introspective)デバグライブラリにおける主な自省関数はデバグである.getinfo.彼の最初のパラメータは、関数またはスタックレベルであってもよい.関数fooに対してdebugを呼び出す.getinfo(foo)は、この関数情報に関するテーブルを返します.この表には、関数が定義されている場所を示すドメインがあります.関数が1つの文字列内で定義されている場合(loadstringによって)、sourceはその文字列です.関数が1つのファイルで定義されている場合、sourceは@にファイル名を付けます.ü short_src、sourceの短いバージョン(最大60文字)で、役に立つエラー情報を記録します.ülinedefined、sourceで関数が定義されている行番号.üwhat、関数タイプを明記します.fooが通常のLua関数であれば、結果は「Lua」である.C関数の場合、結果は「C」です.Luaのメインchunkであれば「main」となります.üname、関数の適切な名前.ünamewhat、前のフィールドが表す意味.このフィールドの値は、W「global」、「local」、「method」、「field」、または「」(空の文字列)です.空の文字列は、Luaがこの関数名を見つけていないことを意味します.ünups、関数のupvaluesの個数.üfunc、関数自体;詳細は後を見る.fooがC関数である場合,Luaは多くの関連情報を知ることができないため,what,name,namewhatのいくつかのドメインの値しか利用できない.数字nでdebugを呼び出す.getinfo(n)の場合、nレベルスタックのアクティブ関数の情報データが返されます.例えば、n=1の場合、呼び出し中の関数の情報が返される.(n=0はC関数getinfoそのものを表す)nがスタック内のアクティブ関数の個数より大きい場合debug.getinfoはnilを返します.数字nを使用してdebugを呼び出すとgetinfoがアクティブ関数の情報をクエリーすると、返される結果tableにはcurrentline、すなわちその時点で関数が存在する行番号という追加のドメインがあります.またfuncはn級を指定するアクティビティ関数を表す.フィールド名の書き方にはいくつかのテクニックがあります.覚えておいてください:Luaでは関数が第1クラスの値であるため、1つの関数に複数の関数名がある可能性があります.指定した値の関数を検索すると、Luaはまずグローバル変数で検索し、見つからない場合はこの関数を呼び出すコードでどのように呼び出されているかを見ます.この場合、getinfoを数値呼び出しで呼び出す場合にのみ機能します.つまり、呼び出しに関する詳細を取得できます.関数getinfoの効率は高くありません.Luaは、プログラム実行を弱めずにdebug情報(Lua keeps debug information in a form that does not impair program execution)を保存し、効率を2位に置く.パフォーマンスをよりよく実行するために、getinfoオプションの2番目のパラメータを使用して、どの情報を選択するかを指定できます.このパラメータを指定すると、プログラムはユーザーが関心を持っていない情報を収集するのに時間を無駄にしません.このパラメータのフォーマットは文字列で、各文字はタイプの情報を表し、使用可能な文字の意味は以下の通りです:'n'selects fields name and namewhat'f'selects field func'S'selects fields source,short_src,what,and linedefined'l'selects field currentline'u'selects field nupの下の関数はdebugを明らかにした.getinfoの使用、関数印刷アクティブスタックの元の追跡情報(traceback):function traceback()local level=1 while true do local info=debug.getinfo(level, "Sl") if not info then break end if info.what == "C"then -- is a C function? print(level,"C function")else--a Lua function print(string.format("%s":%d",info.short_src,info.currentline))end level=level+1 end end endはこの関数を改善することが難しくなく、getinfoがより多くのデータを取得するようにし、実際にdebugライブラリは改善されたバージョンdebugを提供している.traceback、私たちの上の関数とは違います.debug.tracebackは結果を印刷するのではなく、文字列を返します.23.1.1ローカル変数呼び出しdebugライブラリのgetlocal関数にアクセスすると、アクティブなローカル変数にアクセスできます.この関数は、クエリーする関数のスタックレベルと変数のインデックスの2つのパラメータから構成されます.関数には、変数名と変数の現在値の2つの戻り値があります.指定した変数のインデックスがアクティブな変数の数より大きい場合、getlocalはnilを返します.指定したスタックレベルが無効な場合、関数はエラーを放出します.(debug.getinfoを使用してスタックレベルの有効性を確認できます)Luaは、関数に表示されるすべてのローカル変数を順次カウントし、現在の関数の範囲内で有効なローカル変数である場合にのみカウントします.例えば、次のコードfunction foo(a,b)local x do local c=a-b end local a=1 while true do local name,value=debug.getlocal(1,a)if not name then break end print(name,value)a=a+1 end end foo(10,20)の結果,a 10 b 20 x nil a 4インデックスが1の変数はa,2はb,3はx,4は別のaであった.getlocalが呼び出された点で、cは範囲を超えており、nameもvalueも範囲内ではありません.(ローカル変数は初期化後にのみ表示されることを覚えておいてください)debugも使用できます.setlocalはローカル変数の値を変更します.彼の最初の2つのパラメータはスタックレベルと変数インデックスで、3番目のパラメータは変数の新しい値です.この関数は、変数名またはnil(変数インデックスが範囲外の場合)23.1.2を返します.Upvaluesにアクセスするには、debugライブラリのgetupvalue関数からLua関数のupvaluesにアクセスすることもできます.局所変数とは異なり,関数がアクティブでなくてもupvaluesがある(これが閉パケットの意味である).したがって、getupvalueの最初のパラメータはスタックレベルではなく関数(正確には閉パケット)であり、2番目のパラメータはupvalueのインデックスである.Luaはupvalueが1つの関数で参照される順序で順次番号付けされ、1つの関数に同じ名前のupvaluesが2つあることはできないため、この順序はupvalueとはあまり関連がない(relevant).関数ebugを使用できます.setupvalue upvaluesを変更します.彼には3つのパラメータがあるかもしれません.1つの閉パッケージ、1つのupvaluesインデックス、新しいupvalue値です.setlocalと同様に、この関数はupvalueの名前、またはnil(upvalueインデックスがインデックス範囲を超えている場合)を返します.次のコードは、変数名が与えられた場合に、呼び出されている関数の任意の変数の値にアクセスする方法を示します:function getvarvalue(name)local value,found--try local variables local i=1 while true do local n,v=debug.getlocal(2, i) if not n then break end if n == name then value = v found = true end i = i + 1 end if found then return value end -- try upvalues local func = debug.getinfo(2).func i = 1 while true do local n, v = debug.getupvalue(func, i) if not n then break end if n == name then return v end i = i + 1 end -- not found; get global return getfenv(func)[name]endまず、この変数がローカル変数であるかどうかを試します.与えられた名前の変数に複数の変数がある場合は、最高インデックスを持つものにアクセスする必要があります.そのため、ループ全体を巡回する必要があります.ローカル変数に指定した名前の変数が見つからない場合は、upvaluesであるかどうかを試します.まずdebugを使用します.getinfo(2).funcは呼び出した関数を取得し、この関数のupvaluesを巡り、最後に所定の名前の変数を見つけたら、グローバル変数で検索します.注意debugを呼び出す.getlocalとdebug.getinfoのパラメータ2(呼び出し中の関数にアクセスするために使用される)の使い方.