dbx では、ほとんどのイベント管理コマンドでオプションのイベントフィルタ修飾子もサポートします。もっとも単純なフィルタは、プログラムがブレークポイントかトレースハンドラに到達したあと、またはデータ変更ブレークポイントが発生したあとに、dbx に対してある特定の条件をテストするように指示します。
このフィルタの条件が真 (非 0) と評価された場合、イベントコマンドが適用され、プログラムはブレークポイントで停止します。条件が偽 (0) と評価された場合、dbx は、イベントが発生しなかったかのようにプログラムの実行を継続します。
フィルタを含むブレークポイントを設定するには、オプションの -if condition 修飾文を stop コマンドまたは trace コマンドの末尾に追加します。
condition には、任意の有効な式を指定できます。コマンドの入力時に有効だった言語で書かれた、ブール値または整数値を返す関数呼び出しも有効な式に含まれます。
in や at など位置に基づくブレークポイントでは、条件の構文解析を行うスコープはブレークポイント位置のスコープになります。それ以外の場合、イベントではなくエントリ発生時のスコープになります。スコープを正確に指定するために逆引用符演算子 (逆引用符演算子を参照) を使用する必要があることがあります。
次の 2 つのフィルタは異なります。
stop in foo -if a>5 stop cond a>5
前者は foo にブレークポイントが設定され、条件を検査します。後者は自動的に条件を検査します。
フィルタを含むブレークポイントを設定するには、オプションの -if condition 修飾文を stop コマンドまたは trace コマンドの末尾に追加します。condition には、コマンドの入力時に現在の言語でブール値または整数値を返す関数呼び出しも含めて、任意の有効な式を指定できます。
関数呼び出しをブレークポイントフィルタとして使用できます。次の例では、文字列 str の値が abcde の場合、プログラムが関数 foo() で停止します。
(dbx) stop in foo -if !strcmp(“abcde”,str)
関数呼び出しで –if オプションを使用できます。
stop in lookup –if strcmp(name, "troublesome")==0
次に、ウォッチポイントで条件付きフィルタを使用する例を示します。
(dbx) stop access w &speed -if speed==fast_enough
経験の少ないユーザーは、条件付きイベントコマンド (ウォッチタイプのコマンド) の設定と、フィルタの使用を混同することがあります。概念的には、watch タイプのコマンドは、各行の実行前に検査される「前提条件」を作成します (watch のスコープ内で)。ただし、条件付トリガーのあるブレークポイントコマンドでも、それに接続するフィルタを持つことができます。
次の例を考慮します。
(dbx) stop access w &speed -if speed==fast_enough
このコマンドは、変数 speed をモニターするように dbx に指示します。変数 speed に書き込みが行われると (「ウォッチ」部分)、-if フィルタが有効になります。dbx は speed の新しい値が fast_enough と等しいかどうかをチェックします。等しくない場合、プログラムは実行を継続し、stop を「無視」します。
dbx 構文では、フィルタはブレークの「事後」、構文の最後で [-if condition] 文の形式で指定されます。
stop in function [-if condition]
次のようなコードのある類似の例を考慮します。
44: if(open(filename, ...) == -1) 45: return "Error";
次のコマンドによって、open() の ENOENT などの特定のエラーで停止できます。
(dbx) stop at 45 -if errno == 2
局所変数にデータ変更ブレークポイントを配置する際に、フィルタを使用すると便利です。次の例では、現在のスコープは関数 foo() 内にあり、対象となる変数 index は関数 bar() 内にあります。
(dbx) stop access w &bar`index -in bar
bar`index により、関数 foo にある index() 変数や index という名称のグローバル変数ではなく、関数 bar にある index 変数が確実に取り出されます。
-in bar には、次のような意味があります。
関数 bar() に入ると、ブレークポイントが自動的に有効になります。
bar() とそれが呼び出したすべての関数が有効の間は、ブレークポイントは有効の状態を保つ。
bar() からの復帰時に、ブレークポイントは自動的に無効になります。
index に対応するスタック位置は、ほかのいずれかの関数のいずれかの局所変数によって再度利用できます。-in により、ブレークポイントが起動するのは bar`index がアクセスされた場合のみになります。
マルチスレッドプログラムで関数呼び出しを含むフィルタのあるブレークポイントを設定すると、dbx はブレークポイントに達したときにすべてのスレッドの実行を停止し、条件を評価します。条件が合致して関数が呼び出されると、dbx がその呼び出し中すべてのスレッドを再開します。
たとえば、次のブレークポイントを、多くのスレッドが lookup() を呼び出すマルチスレッドアプリケーションで設定する場合があります。
(dbx) stop in lookup -if strcmp(name, “troublesome”) == 0
dbx は、スレッド t@1 が lookup()() を呼び出して条件を評価すると停止し、strcmp()() を呼び出してすべてのスレッドを再開します。dbx が関数呼び出し中に別のスレッドでブレークポイントに達すると、次のいずれかの警告が表示されます。
event infinite loop causes missed events in the following handlers: ...
Event reentrancy first event BPT(VID 6m TID 6, PC echo+0x8) second event BPT*VID 10, TID 10, PC echo+0x8) the following handlers will miss events: ...
そのような場合に、条件式内で呼び出された関数が mutex を取得しないことを確信できる場合は、 -resumeone イベント指定修飾子を使用して、dbx に、ブレークポイントに達した最初の スレッドのみを再開させることができます。たとえば、次のブレークポイントを設定する場合があります。
(dbx) stop in lookup -resumeone -if strcmp(name, “troublesome”) == 0
-resumeone 修飾子はすべての場合において問題を防ぐことはしません。たとえば、次の状況で役立つ場合があります。
条件は再帰的に lookup() を呼び出すため、lookup() の 2 つ目のブレークポイントは最初のスレッドと同じスレッドで発生します。
条件実行が別のスレッドへの制御を放棄するスレッド。
詳細については、イベント指定修飾子を参照してください。