6.10 デバッグ機能
このライブラリは Lua プログラムへのデバッグインターフェース (§ 4.7) に関連する機能を提供します。このライブラリの利用は注意深く行うべきです。いくつかの関数は Lua コードに関する基礎的な仮定を破っています (関数が持つローカルな変数には外部からアクセスできないこと、ユーザーデータのメタテーブルは Lua コードから変更できないこと、Lua プログラムはクラッシュしないことなど)。そのためデバッグライブラリを使うとセキュアなコードがセキュアでなくなる可能性があります。加えていくつかの関数は実行が低速です。
このライブラリの全ての関数は debug
テーブルに公開されます。スレッドに対する操作を行う全ての関数は第一引数が操作するスレッドとなっています。この引数は省略可能であり、省略した場合のデフォルトの値は現在のスレッドです。
debug.debug ()
ユーザーとの対話モードに入り、ユーザーが入力した文字列を一行ずつ実行します。簡単なコマンドと他のデバッグ機能を使って、グローバル変数やローカル変数を確認したり、その値を変更したり、式を評価したりできます。cont
とだけ書かれた行を入力するとこの関数は終了し、呼び出し側が実行を再開します。
debug.debug
で入力するコマンドは字句的にどの関数にもネストされておらず、ローカル変数にアクセスできないことに注意してください。
debug.gethook ([thread])
debug.sethook
関数によって設定された、スレッドのフックに関する現在の設定を表す次の三つの値を返します:
- 現在のフック関数
- 現在のフックマスク
- 現在のフックカウント
アクティブなフックがなければ fail を返します。
debug.getinfo ([thread,] f [, what])
関数の情報を持ったテーブルを返します。f
に関数を直接渡すこともできますが、関数を表す数値を渡すこともできます。f
に数値を渡すと、指定されたスレッドのコールスタックのレベル f
にある関数が処理の対象となります。ここでレベル 0 は現在実行中の関数 (getinfo
そのもの)、レベル 1 は getinfo
を呼び出した関数であり、以下同様です。ただし末尾呼び出しがあるとスタックが変化しないので、この規則は成り立ちません。もし f
がアクティブな関数の数より多いなら、getinfo
は fail を返します。
この関数が返すテーブルは lua_getinfo
が返すフィールドのいずれかを含みます。埋まるフィールドは文字列引数 what
で指定され、デフォルトでは正当な行を表すテーブルを除いた利用可能な全ての情報が取得されます。オプション "f"
は関数自身を "func"
フィールドを追加し、オプション "L"
は正当な行を収めたテーブルを "activelines"
フィールドに追加します。
例えば式 debug.getinfo(1,"n").name
は現在実行中の関数を表す名前を (存在すれば) 返します。また式 debug.getinfo(print)
は print
関数に関する取得可能な全ての情報を含むテーブルを返します。
debug.getlocal ([thread,] f, local)
スタックのレベル f
にある関数が持つインデックス local
のローカル変数の名前と値を返します。この関数は明示的に宣言されたローカル変数だけではなくパラメータおよび一時的な値にもアクセスできます。
一つ目のパラメータまたはローカル変数がインデックス 1 を持ち、以降はコード中で宣言された順番にインデックスが付けられます。インデックスが付くのは指定された関数の現在のスコープでアクティブな変数だけです。またコンパイル時定数は最適化で削除されローカル変数とみなされない可能性があります。負のインデックスは可変長引数を指します (-1 が可変長引数の最初の要素です)。この関数は存在しないインデックスが指定されたとき fail を返し、範囲外のレベルが指定されたときはエラーを送出します (debug.getinfo
を呼べばレベルが正当かどうかを確認できます)。
丸括弧開き '('
で始まる変数名は名前の付いていない変数を表します (ループ制御のための内部変数やデバッグ情報無しにチャンクに保存された変数など)。
パラメータ f
に関数を指定することもできます。この場合 getlocal
はインデックスが local
である関数のパラメータの名前だけを返します。
debug.getmetatable (value)
与えられた value
のメタテーブルを返します。メタテーブルが無ければ nil を返します。
debug.getregistry ()
レジストリテーブル (§ 4.3) を返します。
debug.getupvalue (f, up)
関数 f
が持つインデックス up
のアップバリューの名前と値を返します。指定されたインデックスのアップバリューがなければ fail を返します。
(Lua 関数のアップバリューとは関数がアクセスする外部ローカル変数であり、クロージャに含まれます)
C 関数に対してこの関数を使うと、全てのアップバリューの名前が空文字列 ""
となります。
名前が存在しない変数 (デバッグ情報無しにチャンクに保存された変数) の名前はクエスチョンマーク '?'
となります。
debug.getuservalue (u, n)
ユーザーデータ u
に関連付いた n
個目のユーザーバリュー、および指定されたユーザーデータにその値が存在しない場合に false となる真偽値を返します。
debug.setcstacklimit (limit)
C スタックの新しい上限を設定します。この値は Lua におけるネストされた呼び出しの深さの上限であり、スタックオーバーフローを避けるために用意されています。上限が小さすぎると、再帰呼び出しが意味もなく制限されます。一方で上限が大きすぎると、インタープリタがスタックオーバーフローを起こす可能性が生じます。残念ながら、プラットフォームにおける安全な上限の最大値を事前に取得する方法はありません。
Lua コードが行う関数呼び出しが一単位のコストとしてカウントされます。C からの呼び出しやコルーチンの再開と言った操作はこれ以上のコストとしてカウントされます。
この関数には次の制限があります:
- 呼び出せるのはメインルーチン (スレッド) だけ。
- スタックオーバーフローエラーを処理している間は呼び出せない。
limit
は 40000 以下でなければならない。limit
は現在の C スタック使用量より小さくてはいけない。
この制限を守らないで呼び出すと偽値が返ります。そうでなければ古い上限が返ります。
debug.sethook ([thread,] hook, mask [, count])
与えられた関数をデバッグフックとして設定します。文字列 mask
と数値 count
はフックが呼ばれるタイミングを表します。mask
に使える文字とその意味は次の通りです:
'c'
: フックは Lua が関数を呼ぶたびに呼ばれる。'r'
: フックは Lua が関数から返るたびに呼ばれる。'l'
: フックは Lua がコードの新しい行に入るたびに呼ばれる。
加えて count
が 0 でないときは命令を count
個実行するたびに呼ばれます。
引数を渡さずに呼ぶと、debug.sethook
はフックを無効化します。
フックが呼ばれるときの第一パラメータはフックを呼び出したイベントを表す文字列であり、"call"
, "tail call"
, "return"
, "line"
, "count"
のいずれかです。ラインイベントではさらに新しい行番号が第二パラメータとしてフックに渡されます。フック内部では debug.getinfo
をレベル 2 に対して呼ぶことで実行中の関数に関するさらなる情報を入手できます (レベル 0 が getinfo
で、レベル 1 がフック関数です)。
debug.setlocal ([thread,] level, local, value)
スタックのレベル level
にある関数が持つインデックス local
のローカル変数の値に value
を代入します。指定されたインデックスにローカル変数がなければ fail を返し、level
が範囲外であればエラーを送出します (level
が正当かどうかは debug.getinfo
で確認できます)。それ以外の場合は処理が行われたローカル変数の名前を返します。
変数のインデックスと名前について詳しくは debug.getlocal
を参照してください。
debug.setmetatable (value, table)
与えられた value
のメタテーブルを与えられた table
に設定します (table
は nil でも構いません)。value
を返します。
debug.setupvalue (f, up, value)
関数 f
が持つインデックス up
のアップバリューに value
を代入します。指定されたインデックスを持つアップバリューがなければ fail を返し、そうでなければアップバリューの名前を返します。
アップバリューについて詳しくは debug.getupvalue
を参照してください。
debug.setuservalue (udata, value, n)
udata
に関連付いた n
個目のユーザーバリューを value
に設定します。udata
はフルユーザーデータでなければなりません。
成功すれば udata
を返しますが、ユーザーデータが指定されたユーザーバリューを持たない場合には fail を返します。
debug.traceback ([thread,] [message [, level]])
文字列でも nil でもない message
が与えられた場合には、何も処理せずに message
を返します。それ以外の場合はコールスタックのトレースバックを含んだ文字列を返します。省略可能な文字列 message
はトレースバックの先頭に追加されます。省略可能な数値 level
はトレースバックを始めるレベルを表します (デフォルトは traceback
を呼び出した関数を表す 1 です)。
debug.upvalueid (f, n)
与えられた関数 f
が持つインデックス n
のアップバリューを示すユニークな識別子を (ライトユーザーデータとして) 返します。
このユニークな識別子を使えば、異なるクロージャがアップバリューを共有するかをプログラムから判定できます。アップバリューを共有する (同じ外部ローカル変数にアクセスする) Lua クロージャはそのアップバリューのインデックスに対して同じ識別子を返します。
debug.upvaluejoin (f1, n1, f2, n2)
Lua クロージャ f1
の n1
番目のアップバリューの参照先を、Lua クロージャ f2
の n2
番目のアップバリューとします。