ループ内で問題が発生したものをデバッグしているとき、たとえば600回目の反復では、すべてを中断しなければならないのは面倒な場合があります。そこで、条件付きブレークポイントを設定して、I = 600の場合にのみブレークするようにしました。これは機能しますが、そのポイントに到達するまでにほぼ1分かかります。以前は、ほぼ瞬時でした。何が起こっているのですか、それを修正する方法はありますか?
6 に答える
ブレークポイントに到達すると、Windowsはプロセスを停止し、デバッガーに通知します。コンテキストを切り替え、条件を評価し、いいえ、通知されたくないと判断し、プロセスを再開して、元に戻す必要があります。これには、多くのプロセッササイクルがかかる可能性があります。タイトなループで実行している場合は、ループの1回の反復よりも数桁多くのプロセッササイクルが必要になります。
コードを少し混乱させたい場合は、このオーバーヘッドをすべて発生させることなく、条件付きブレークポイントを実行する方法があります。
if <condition here> then
asm int 3 end;
これは、OSにブレークポイント通知を手動で送信する単純なアセンブリ命令です。これで、コンテキストを切り替えることなく、プログラム内の状態を評価できます。使い終わったら、必ずもう一度取り出してください。デバッガーに接続されていないプログラム内でint3がオフになると、例外が発生します。
あなたがそのポイントに到達するたびに、あなたの状態をチェックしなければならないので、それはそれを遅くします.
私がよく行うのは、このような別の変数を一時的に作成することです (C ではありますが、Delphi では実行できるはずです)。
int xyzzynum = 600;
while (true) {
doSomething();
if (--xyzzynum == 0)
xyzzynum = xyzzynum;
}
次に、無条件のブレークポイントを"xyzzynum = xyzzynum;"
行に配置しました。
デバッガーは毎回条件をチェックするのではなく、通常のブレークポイント割り込みを実行しているだけなので、プログラムはループを 600 回通過するまで全速力で実行されます。
必要に応じて条件を複雑にすることができます。
メイソンの答えに加えて、定義されたデバッグ条件付きでプログラムがビルドされている場合にのみ、 int 3 アセンバーをコンパイルすることができます。
{$ifdef debug}
{$message warn 'debug breakpoint present in code'}
if <condition here> then
asm int 3 end;
{$endif}
そのため、IDE でデバッグする場合、プロジェクト オプションでデバッグ条件を設定できます。顧客向けの最終製品を (ビルド スクリプトを使用して) ビルドするときは、そのシンボルを含めないため、コンパイルされません。
$message コンパイラ ディレクティブも含めたので、コンパイル時に、コードがまだそこにあることを知らせる警告が表示されます。int 3 を使用しているすべての場所でこれを行うと、問題のあるコードに直接移動するためにダブルクリックできる場所の素晴らしいリストが表示されます。
N@
メイソンの説明はとても良いです。
彼のコードは、デバッガーで実行することをテストすることで、もう少し安全にすることができます。
if (DebugHook <> 0) and <your specific condition here> then
asm int 3 end;
これは、アプリケーションが正常に実行されている場合は何もせず、デバッガーで実行されている場合は停止します (IDE から起動された場合でも、デバッガーに接続されている場合でも)。また、デバッガーを使用していない場合
、ブール値のショートカットは評価されません。<your specific condition here>
デバッガーの条件付きブレークポイント(ここで推測しているだけです)では、ブレークポイントに到達するたびに、プログラムとデバッガーの間で毎回プロセスを切り替える必要があります。このプロセスには時間がかかりますが、できることは何もないと思います。
通常、条件ブレークポイントは、適切なブレーク命令をコードに挿入し、指定した条件をチェックすることによって機能します。反復ごとにチェックされますが、デバッガーが完全なチェックおよびブレークポイント コードをコンパイルして既存のコードに挿入する可能性は低いため、チェックの実装方法が遅延の原因である可能性があります。
これを加速できる可能性がある方法は、条件の後に副作用のない操作をコードに直接配置し、その操作を中断することです。完了したら、必ず条件と op を削除してください。