19

Visual Studioでトレースポイントを作成する場合(ブレークポイントを右クリックして[ヒットした場合...]を選択)、ダイアログには次のテキストが表示されます。

中括弧で囲むことにより、変数または他の式の値をメッセージに含めることができます。

どのような表現が許可されていますか?

4

2 に答える 2

18

Microsoftのドキュメントは、許可されているものと許可されていないものの正確な詳細についてはかなりまばらです。以下のほとんどは、イミディエイトウィンドウでの試行錯誤によって見つかりました。このリストはC++用であることに注意してください。これは、私がコーディングしたものです。C#を信じているので、以下の禁止されている項目のいくつかは実際に許可されています。

キャスト、変数の設定、関数の呼び出しなど、ほとんどの基本的な式を評価できます。

一般的な制限
  • Cスタイルのキャストのみがサポートされています。static_cast、dynamic_cast、reinterpret_cast、const_castはありません
  • 新しい変数を宣言したり、オブジェクトを作成したりすることはできません
  • オーバーロードされた演算子は使用できません
  • 三項演算子が機能しない
  • Visual Studioはコンマ演算子を使用して式の結果をフォーマットするため、コンマ演算子は使用できません。複数の式に複数の中括弧を使用する
関数呼び出し
  • 禁止されている通話:
    • ラムダ(定義したり呼び出したりすることはできません)
    • 匿名の名前空間で機能する
    • オブジェクトを値で受け取る関数(オブジェクトを作成できないため)
  • 許可された通話:
    • 通常および仮想の両方のメンバー関数
    • 基本型またはクラス型のいずれかへの参照またはポインターを受け取る関数
    • スコープ内変数の受け渡し
    • 「&」を使用してスコープ内の変数にポインタを渡す
    • リテラル「true」、「false」、数字を渡す
    • 「オブジェクトを作成できない」ルールに違反しない限り、文字列リテラルを渡す
    • 中括弧の複数のセットを使用して、1つのトレースポイントで複数の関数を呼び出す
変数の割り当て
  • 禁止:
    • オブジェクト
    • 文字列リテラル
  • 許可:
    • 基本型の変数、リテラルまたは他の変数からの値
    • キャスト後のメモリアドレス:{ *(bool*)(0x1234) = true }
    • レジスター:{ @eip = 0x1234 }

ユースケース

トレースポイントから関数を呼び出すことは非常に強力です。慎重に設定された関数と適切な呼び出しにより、上記の制限のほとんどを回避できます。ここにいくつかのより具体的なアイデアがあります。

ifを強制する

非常に簡単です。トレースポイントを設定して変数を設定し、テストする必要があるものに応じて、if条件をtrueまたはfalseに強制します。コードを追加したり、デバッグセッションを終了したりすることなくすべて。

ブレークポイントの「切り替え」

「頻繁にヒットする場所でブレークする必要があります。別のブレークポイントからそのブレークポイントを有効にしたいので、気になるものは特定のコードからのブレークのみを取得します。パス。どうすればそれができますか?」上記の知識があれば、ヘルパー変数は必要ですが、簡単です。

  1. falseに設定されたグローバルブール値を作成します。
  2. グローバルフラグがtrueの場合にのみブレークする条件を使用して、最終的な宛先にブレークポイントを作成します。
  3. グローバルフラグをtrueに割り当てるクリティカルスポットにトレースポイントを設定します。

良い点は、デバッグセッションを終了せずにトレースポイントを移動できることです。再度実行する必要がある場合は、イミディエイトウィンドウまたはウォッチウィンドウを使用してグローバルフラグをリセットします。完了したら、クリーンアップする必要があるのはそのグローバルブール値だけです。削除する他のコードはありません。

コードを自動的にスキップする

EIPレジスタ(少なくともx86では)は命令ポインタです。割り当てると、プログラムフローを変更できます。

  1. [登録]ウィンドウまたは[@eip、x]が表示された[監視]ウィンドウで、スキップする行のアドレスを1回中断し、EIPの値を確認して見つけます。([レジスタ]ウィンドウの値は16進数ですが、先頭に「0x」がないことに注意してください。)
  2. 手順1のアドレスを使用して、スキップする行に、のような式でトレースポイントを追加します。{@eip = address}
  3. EIP割り当ては、回線上の何かが実行される前に行われます。

これは便利ですが、このようなコードをスキップすると奇妙な動作を引き起こす可能性があるため、注意してください。

于 2013-02-04T21:12:34.023 に答える
2

Kurt Hutchinsonが言うように、文字列の割り当てはトレースポイントでは許可されていません。これを回避するには、文字列変数を割り当てるメソッドを作成し、それを呼び出します。

public static class Helper
{
    public static void AssignTo(this string value, out string variable)
    {
        variable = value;
    }
}

次に、トレースポイントメッセージで:

{"new string value".AssignTo(out stringVariable)}
于 2017-04-18T12:17:47.663 に答える