Lua デバッグ(Debug)

Lua は、独自のデバッガを作成するための機能を提供する debug ライブラリを提供しています。Lua 自体には組み込みのデバッガはありませんが、多くの開発者が自身の Lua デバッガのコードを共有しています。

Lua の debug ライブラリには以下の関数が含まれています:

番号メソッド & 用途
1.debug():

ユーザー対話モードに入り、ユーザーが入力した各文字列を実行します。簡単なコマンドやその他のデバッグ設定を使用して、ユーザーはグローバル変数とローカル変数を調べたり、変数の値を変更したり、いくつかの式を評価したりすることができます。
cont のみを含む行を入力するとこの関数は終了し、呼び出し元は実行を続行できます。

2.getfenv(object):

オブジェクトの環境を返します。

3.gethook(optional thread):

スレッドのフック設定を表す3つの値を返します:現在のフック関数、現在のフックマスク、現在のフックカウント。

4.getinfo ([thread,] f [, what]):

関数に関する情報を含むテーブルを返します。関数を直接指定するか、数値 f で関数を指定できます。数値 f は、指定されたスレッドの呼び出しスタックの対応するレベルで実行されている関数を表します:レベル 0 は現在の関数(getinfo 自身)、レベル 1 は getinfo を呼び出した関数(末尾呼び出しの場合はスタックにカウントされません)、などです。f がアクティブな関数の数よりも大きい場合、getinfo は nil を返します。

5.debug.getlocal ([thread,] f, local):

この関数は、スタックの f レベルの関数の、インデックス local のローカル変数の名前と値を返します。この関数は、明示的に定義されたローカル変数だけでなく、仮引数や一時変数などにもアクセスするために使用されます。

6.getmetatable(value):

指定されたインデックスが指す値のメタテーブルをスタックにプッシュします。インデックスが無効であるか、その値にメタテーブルがない場合、関数は 0 を返し、スタックには何もプッシュしません。

7.getregistry():

レジストリテーブルを返します。これは事前定義されたテーブルで、任意の C コードが保存したい Lua 値を保存するために使用できます。

8.getupvalue (f, up)

この関数は、関数 f の up 番目のアップバリューの名前と値を返します。その関数にそのアップバリューがない場合、nil を返します。
'('(開き括弧)で始まる変数名は、名前のない変数(デバッグ情報が除去されたコードブロック)を表します。

10.sethook ([thread,] hook, mask [, count]):

関数をフック関数として設定します。文字列 mask と数値 count によって、フックがいつ呼び出されるかが決まります。マスクは以下の文字を組み合わせた文字列で、各文字には意味があります:

  • 'c': Lua が関数を呼び出すたびにフックが呼び出されます;
  • 'r': Lua が関数から戻るたびにフックが呼び出されます;
  • 'l': Lua が新しい行に入るたびにフックが呼び出されます。
11.setlocal ([thread,] level, local, value):

この関数は、スタック上の level レベルの関数の local 番目のローカル変数に value を代入します。その変数が存在しない場合、関数は nil を返します。level が範囲外の場合はエラーを発生させます。

12.setmetatable (value, table):

value のメタテーブルを table(nil も可)に設定します。value を返します。

13.setupvalue (f, up, value):

この関数は、関数 f の up 番目のアップバリューに value を設定します。その関数にそのアップバリューがない場合は nil を返し、それ以外の場合はそのアップバリューの名前を返します。

14.traceback ([thread,] [message [, level]]):

message が存在し、文字列でも nil でもない場合、関数は何も処理せずにそのまま message を返します。それ以外の場合は、呼び出しスタックのバックトレース情報を返します。オプションの文字列 message はバックトレース情報の先頭に追加されます。オプションの数値 level は、スタックのどのレベルからバックトレースを開始するかを指定します(デフォルトは 1、つまり traceback を呼び出した位置です)。

上の表は、よく使用されるデバッグ関数を示しています。次に、いくつかの簡単な例を見てみましょう:

実例

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 関数は関数情報のテーブルを返すために使われます。

別の実例

関数内のローカル変数をデバッグする必要がよくあります。これらのローカル変数を設定するには、setupvalue 関数を使用できます。例は次のとおりです:

実例

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 に設定しました。次に関数を呼び出すと、実行後の出力は 3 ではなく 11 になります。


デバッグの種類

  • コマンドラインデバッグ
  • グラフィカルインターフェースデバッグ

コマンドラインデバッガには、RemDebug、clidebugger、ctrace、xdbLua、LuaInterface - Debugger、Rldb、ModDebug などがあります。

グラフィカルインターフェースのデバッガには、SciTE、Decoda、ZeroBrane Studio、akdebugger、luaedit などがあります。

その他の拡張