1

時々、Visual Studio デバッガーが無効な現在の命令を表示することがあります。考えられる最も単純な理由は次のとおりです。

  • 古い .pdb ファイル。これらのファイルには、バイナリ ファイルのどのオフセットがどのコード行に対応するかに関する情報が含まれています。これらのファイルが古い場合、明らかにデバッガーは無効な行を表示します。
  • デバッグではなくリリース モードでコンパイルされたプログラム。リリース モードでは通常、最適化がオンになっているため、オプティマイザーはコードをより高速 (またはより小さく) に変更できます。このような場合、バイナリ ファイルはソース コードに対応しなくなるため、デバッガーは実際に実行された行を表示できません。

しかし、私の場合は違いました。ソース コード (C#) の一部を次に示します。

if (match.Groups.Count != 4)
    throw new InvalidOperationException("Internal error: Invalid regular expression!");

MyEnum myEnum;
try
{
    // (...)

ソースをデバッグしました。デバッガーは条件ステートメントで停止し、match.Groups.Count実際には 4 に等しいことが示されました。明らかに、throw ステートメントはスキップされるべきでしたが、驚くべきことに、そうではありませんでした。ただし、ステートメントを「実行」した後throw、デバッガーは次の有効なステートメントに移動し、想定どおりに実行を続けました。

どうしたの?

4

1 に答える 1

1

このような場合、通常は分解を検討する価値があります。私の場合、次のようになりました。

    if (match.Groups.Count != 4)

00000344  mov         rax,qword ptr [rbp+30h] 
00000348  mov         rax,qword ptr [rax] 
(...)
00000399  test        eax,eax 
0000039b  jne         00000000000003ED // (1)

    throw new InvalidOperationException("Internal error: Invalid regular expression!");

0000039d  lea         rdx,[00049AC0h] 
000003a4  mov         ecx,7000024Eh 
000003a9  call        000000005F7CC994 
(...)
000003dc  call        000000005ED32730 
000003e1  mov         rcx,qword ptr [rbp+000000F8h] 
000003e8  call        000000005F7CC64C 
000003ed  nop // (2)

    MyEnum myEnum;
    try
    {

000003ee  nop // (3)

jne命令 (1)にブレークポイントを設定します。アセンブラをよく知らない人 (私は実際には知らない) のために、条件付きステートメントはペアにコンパイルされることよくありtestます。したがって、ブレークポイントを設定する場所は、throw ステートメントを実行するかどうかの最終決定でした。jne

ステップオーバー (F10) の後、デバッガーは (2) の場所にジャンプしたため、throw ステートメントを正しくスキップしました。繰り返しますが、それを知らない人のために、nop( No operation ) はアセンブラ命令であり、実際には何もしません。コンパイラは通常、それを使用してアセンブリコードを調整し、パフォーマンスを向上させます(低レベルのプロセッサのものだと思います)。

しかし、コンパイラは情報を台無しにして .pdb ファイルに保存しました。これはステートメントnopの一部です。throwデバッガーはそれを読み取り、現在の命令マーカーをthrowステートメントに配置しました。しかし、実際のアセンブリ コードが正しかったため、それを実行し (何もせず)、実行を続けました。

誰かが同様の問題で立ち往生していることに気付いた場合に備えて、この例を残します。原因を見つけるのに役立つことを願っています。遭遇することはかなりまれですが、誰が知っていますか...

于 2013-05-23T10:20:16.927 に答える