有时会发生Visual Studio调试器显示无效的当前指令。最简单的原因是:
但我的情况有所不同。这是一段源代码(C#):
if (match.Groups.Count != 4)
throw new InvalidOperationException("Internal error: Invalid regular expression!");
MyEnum myEnum;
try
{
// (...)
我调试了源代码。调试器在条件语句处停止并显示,match.Groups.Count
实际上等于4.显然,应该跳过throw语句,但令人惊讶的是,不是。但是,在“执行”throw
语句之后,调试器转到下一个有效语句并继续按预期执行。
发生了什么事?
答案 0 :(得分: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
和某种条件跳转,例如jne
(< b> j ump如果 n ot e qual)。所以我设置断点的地方实际上是最终决定,是否执行throw语句。
在跳过(F10)之后,调试器跳转到(2)位置,因此它正确地跳过了throw语句。对于那些不知道这一点的人来说,nop
( N o op eration)是一个汇编指令,它实际上什么都不做。编译器通常使用它来对齐汇编代码,这样它的性能会更好(我想是低级处理器的东西)。
但是编译器搞砸了并将信息保存在.pdb文件中,提到nop
是throw
语句的一部分。调试器读取并将当前指令标记放在throw
语句上。但是,它只是执行它(什么都不做)并继续执行,因为实际的汇编代码是正确的。
我留下这个例子以防万一有人发现自己陷入了类似的问题 - 希望这有助于找到原因。遇到这种情况相当罕见,但谁知道呢?...