C# 如果语句工作不正确-反汇编对我来说没有任何解释
我遇到了一个非常奇怪的问题 我正在开发一些连接到Web服务的类库。该库由桌面应用程序使用 在我现在的代码中:C# 如果语句工作不正确-反汇编对我来说没有任何解释,c#,disassembly,C#,Disassembly,我遇到了一个非常奇怪的问题 我正在开发一些连接到Web服务的类库。该库由桌面应用程序使用 在我现在的代码中: Int32 errorCode32 = errorCode; Int32 errorTimeout = 300; if (errorCode32.Equals(errorTimeout) == false) { System.Console.Out.WriteLine("aaa"); return; } 其中errorCode等于300。因此,乍一看,if error
Int32 errorCode32 = errorCode;
Int32 errorTimeout = 300;
if (errorCode32.Equals(errorTimeout) == false)
{
System.Console.Out.WriteLine("aaa");
return;
}
其中errorCode等于300。因此,乍一看,if errorCode==300时,if语句中的代码不应执行,因为它被定义为仅在errorCode不等于300时执行
直到现在一切都很清楚,但现在一切都开始了
应用程序正在运行,并执行带有上述代码段的方法。errorCode等于300,这是预期的结果,即应用程序不会执行if语句中的任何代码,因为整个语句为false。但实际上,应用程序进入“if”内部并立即跳转到“return”语句。系统控制台输出。。。永远不会被执行。如果我将干净的“return”语句替换为“thrownewsomeexception()”
我会得到同样的结果。应用程序进入if语句(注意:[errorCode32.Equals(errorTimeout)==false]在我的例子中为false],不执行Console.Out。。。但也有例外
我多次重建了所有内容,删除了所有二进制文件,甚至从磁盘上删除了整个项目,并再次从存储库中检索到“清理”文件夹
我非常困惑,甚至将代码反汇编以查看发生了什么(即使我不是汇编专家)。但结果对我来说很奇怪
反汇编代码如下:
50: Int32 errorCode32 = errorCode;
000000e5 mov eax,dword ptr [ebp-50h]
000000e8 mov dword ptr [ebp-54h],eax
51: Int32 errorTimeout = 300;
000000eb mov dword ptr [ebp-58h],12Ch
52:
53: if (errorCode32.Equals(errorTimeout) == false)
000000f2 lea ecx,[ebp-54h]
000000f5 mov edx,dword ptr [ebp-58h]
000000f8 call 699EB198
000000fd mov dword ptr [ebp-68h],eax
00000100 movzx eax,byte ptr [ebp-68h]
00000104 mov dword ptr [ebp-48h],eax
00000107 cmp dword ptr [ebp-48h],0
0000010b jne 00000134
54: {
0000010d nop
55: System.Console.Out.WriteLine("aaa");
0000010e call 69538768
00000113 mov dword ptr [ebp+FFFFFF7Ch],eax
00000119 mov edx,dword ptr ds:[0302CE30h]
0000011f mov ecx,dword ptr [ebp+FFFFFF7Ch]
00000125 mov eax,dword ptr [ecx]
00000127 call dword ptr [eax+000000D8h]
0000012d nop
56: return;
0000012e nop
0000012f jmp 00000287
00000134 mov eax,dword ptr ds:[0302CE34h]
0000013a mov dword ptr [ebp-6Ch],eax
0000013d mov edx,5
00000142 mov ecx,6EDE3FBEh
00000147 call FA68D488
0000014c mov dword ptr [ebp-70h],eax
57: }
当我调试指令时,我可以理解发生了什么,直到行:
00000104 mov dword ptr [ebp-48h],eax
我预计eax中存储的值将被复制到位置“dword ptr[ebp-48h]”,应用程序将转到下一行(00000107)。但这并没有发生。当我试图跳过第00000104行时,应用程序立即跳到第00000104行
00000134 mov eax,dword ptr ds:[0302CE34h]
我不明白这里发生了什么。我试图在网上搜索,但找不到任何有用的东西。有没有人对问题的原因或解决方法有什么建议
编辑 我忘了把我正在使用VisualStudio2008并编译到.NET3.5中的信息放进去。 所有更新都已安装
编辑 C语言中的整型方法# 拆卸和拆卸:
34: private void nativeDocumentServiceWrapper_PostInvokeEvents(object sender, WebServiceInvokeEventArgs e)
35: {
00000000 push ebp
00000001 mov ebp,esp
00000003 push edi
00000004 push esi
00000005 push ebx
00000006 sub esp,84h
0000000c mov esi,ecx
0000000e lea edi,[ebp-54h]
00000011 mov ecx,12h
00000016 xor eax,eax
00000018 rep stos dword ptr es:[edi]
0000001a mov ecx,esi
0000001c xor eax,eax
0000001e mov dword ptr [ebp-1Ch],eax
00000021 mov dword ptr [ebp-3Ch],ecx
00000024 mov dword ptr [ebp-40h],edx
00000027 cmp dword ptr ds:[01AD2DD8h],0
0000002e je 00000035
00000030 call 6AB8A719
00000035 mov dword ptr [ebp-48h],0
0000003c xor edx,edx
0000003e mov dword ptr [ebp-5Ch],edx
00000041 xor edx,edx
00000043 mov dword ptr [ebp-44h],edx
00000046 xor edx,edx
00000048 mov dword ptr [ebp-4Ch],edx
0000004b xor edx,edx
0000004d mov dword ptr [ebp-58h],edx
00000050 nop
36: Exception exception = e.Exception;
00000051 mov eax,dword ptr [ebp+8]
00000054 mov eax,dword ptr [eax+4]
00000057 mov dword ptr [ebp-44h],eax
37: if (exception == null)
0000005a cmp dword ptr [ebp-44h],0
0000005e setne al
00000061 movzx eax,al
00000064 mov dword ptr [ebp-48h],eax
00000067 cmp dword ptr [ebp-48h],0
0000006b jne 0000007F
38: {
0000006d nop
39: _invokeRetries = 0;
0000006e mov eax,dword ptr [ebp-3Ch]
00000071 xor edx,edx
00000073 mov dword ptr [eax+00000088h],edx
40: return;
00000079 nop
0000007a jmp 00000287
41: }
42:
43: string errorCodeString = ErrorHandler.GetErrorCodeString(exception);
0000007f mov ecx,dword ptr [ebp-44h]
00000082 call FF0827F0
00000087 mov dword ptr [ebp-60h],eax
0000008a mov eax,dword ptr [ebp-60h]
0000008d mov dword ptr [ebp-4Ch],eax
44: int errorCode;
45: if (int.TryParse(errorCodeString, out errorCode))
00000090 lea edx,[ebp-50h]
00000093 mov ecx,dword ptr [ebp-4Ch]
00000096 call 694B44A8
0000009b mov dword ptr [ebp-64h],eax
0000009e cmp dword ptr [ebp-64h],0
000000a2 sete al
000000a5 movzx eax,al
000000a8 mov dword ptr [ebp-48h],eax
000000ab cmp dword ptr [ebp-48h],0
000000af jne 000000E5
46: {
000000b1 nop
47: e.Exception = new VaultException(errorCode, exception);
000000b2 mov ecx,5482E0Ch
000000b7 call FA68D364
000000bc mov dword ptr [ebp+FFFFFF78h],eax
000000c2 push dword ptr [ebp-44h]
000000c5 mov edx,dword ptr [ebp-50h]
000000c8 mov ecx,dword ptr [ebp+FFFFFF78h]
000000ce call FF07FCB0
000000d3 mov edx,dword ptr [ebp+8]
000000d6 mov eax,dword ptr [ebp+FFFFFF78h]
000000dc lea edx,[edx+4]
000000df call 6A90E288
48: }
000000e4 nop
49:
50: Int32 errorCode32 = errorCode;
000000e5 mov eax,dword ptr [ebp-50h]
000000e8 mov dword ptr [ebp-54h],eax
51: Int32 errorTimeout = 300;
000000eb mov dword ptr [ebp-58h],12Ch
52:
53: if (errorCode32.Equals(errorTimeout) == false)
000000f2 lea ecx,[ebp-54h]
000000f5 mov edx,dword ptr [ebp-58h]
000000f8 call 699EB198
000000fd mov dword ptr [ebp-68h],eax
00000100 movzx eax,byte ptr [ebp-68h]
00000104 mov dword ptr [ebp-48h],eax
00000107 cmp dword ptr [ebp-48h],0
0000010b jne 00000134
54: {
0000010d nop
55: System.Console.Out.WriteLine("aaa");
0000010e call 69538768
00000113 mov dword ptr [ebp+FFFFFF7Ch],eax
00000119 mov edx,dword ptr ds:[0302CE30h]
0000011f mov ecx,dword ptr [ebp+FFFFFF7Ch]
00000125 mov eax,dword ptr [ecx]
00000127 call dword ptr [eax+000000D8h]
0000012d nop
56: return;
0000012e nop
0000012f jmp 00000287
00000134 mov eax,dword ptr ds:[0302CE34h]
0000013a mov dword ptr [ebp-6Ch],eax
0000013d mov edx,5
00000142 mov ecx,6EDE3FBEh
00000147 call FA68D488
0000014c mov dword ptr [ebp-70h],eax
57: }
58:
59: Trace.TraceWarning("Invoke failed (count: {4}) {0}.{1} #{2} error '{3}'", _moduleName, e.MethodName, _id, errorCodeString, _invokeRetries + 1);
0000014f mov eax,dword ptr [ebp-70h]
00000152 mov dword ptr [ebp-5Ch],eax
00000155 mov eax,dword ptr [ebp-3Ch]
00000158 push dword ptr [eax+00000080h]
0000015e mov ecx,dword ptr [ebp-5Ch]
00000161 xor edx,edx
00000163 call 6A914654
00000168 mov eax,dword ptr [ebp+8]
0000016b push dword ptr [eax+8]
0000016e mov ecx,dword ptr [ebp-5Ch]
00000171 mov edx,1
00000176 call 6A914654
0000017b mov ecx,6F052DA0h
00000180 call FA68D364
00000185 mov dword ptr [ebp-74h],eax
00000188 mov eax,dword ptr [ebp-5Ch]
0000018b mov dword ptr [ebp+FFFFFF74h],eax
00000191 mov eax,dword ptr [ebp-3Ch]
00000194 mov eax,dword ptr [eax+00000084h]
0000019a mov edx,dword ptr [ebp-74h]
0000019d mov dword ptr [edx+4],eax
000001a0 mov eax,dword ptr [ebp-74h]
000001a3 push eax
000001a4 mov ecx,dword ptr [ebp+FFFFFF74h]
000001aa mov edx,2
000001af call 6A914654
000001b4 push dword ptr [ebp-4Ch]
000001b7 mov ecx,dword ptr [ebp-5Ch]
000001ba mov edx,3
000001bf call 6A914654
000001c4 mov ecx,6F052DA0h
000001c9 call FA68D364
000001ce mov dword ptr [ebp-78h],eax
000001d1 mov eax,dword ptr [ebp-5Ch]
000001d4 mov dword ptr [ebp+FFFFFF70h],eax
000001da mov eax,dword ptr [ebp-3Ch]
000001dd mov eax,dword ptr [eax+00000088h]
000001e3 inc eax
000001e4 mov edx,dword ptr [ebp-78h]
000001e7 mov dword ptr [edx+4],eax
000001ea mov eax,dword ptr [ebp-78h]
000001ed push eax
000001ee mov ecx,dword ptr [ebp+FFFFFF70h]
000001f4 mov edx,4
000001f9 call 6A914654
000001fe mov edx,dword ptr [ebp-5Ch]
00000201 mov ecx,dword ptr [ebp-6Ch]
00000204 call 69039D88
00000209 nop
60:
61: if (_invokeRetries > 0)
0000020a mov eax,dword ptr [ebp-3Ch]
0000020d cmp dword ptr [eax+00000088h],0
00000214 setle al
00000217 movzx eax,al
0000021a mov dword ptr [ebp-48h],eax
0000021d cmp dword ptr [ebp-48h],0
00000221 jne 00000273
62: {
00000223 nop
63: //int errorCode;
64: if (int.TryParse(errorCodeString, out errorCode))
00000224 lea edx,[ebp-50h]
00000227 mov ecx,dword ptr [ebp-4Ch]
0000022a call 694B44A8
0000022f mov dword ptr [ebp-7Ch],eax
00000232 cmp dword ptr [ebp-7Ch],0
00000236 sete al
00000239 movzx eax,al
0000023c mov dword ptr [ebp-48h],eax
0000023f cmp dword ptr [ebp-48h],0
00000243 jne 00000270
65: {
00000245 nop
66: //throw new VaultException(errorCode, exception);
67: e.Exception = new VaultException(errorCode, exception);
00000246 mov ecx,5482E0Ch
0000024b call FA68D364
00000250 mov dword ptr [ebp-80h],eax
00000253 push dword ptr [ebp-44h]
00000256 mov edx,dword ptr [ebp-50h]
00000259 mov ecx,dword ptr [ebp-80h]
0000025c call FF07FCB0
00000261 mov edx,dword ptr [ebp+8]
00000264 mov eax,dword ptr [ebp-80h]
00000267 lea edx,[edx+4]
0000026a call 6A90E288
68: }
0000026f nop
69: return;
00000270 nop
00000271 jmp 00000287
70: }
71:
72: e.Exception = null;
00000273 mov eax,dword ptr [ebp+8]
00000276 xor edx,edx
00000278 mov dword ptr [eax+4],edx
73:
74: // we ran into error 300 or 319
75: // the solution is to log in again and re-run the command
76:
77: tryReloginAndInvokeVaultMethodAgain(e);
0000027b mov edx,dword ptr [ebp+8]
0000027e mov ecx,dword ptr [ebp-3Ch]
00000281 call FF0876C0
00000286 nop
78: }
您启用了优化,编译器将
if
语句中的return语句与函数末尾的语句组合在一起。这两行代码的地址相同,调试器无法判断要突出显示哪一行源代码,因为两者都匹配
没什么不对的。但是,如果您希望单步执行调试器以正常工作,则必须禁用优化
这只是优化器可以用来混淆调试器的几件事情之一。其他的可能性是对没有数据依赖关系的语句进行重新排序(以优化管道),甚至将语句拆分并在语句之间放置另一个语句。我花了更多的时间研究这个问题,我有一些结论想与大家分享,即使这意味着我必须承认,我做出了一些错误的假设,我无法从整体上了解整个行为 第一:我介绍的代码旨在处理使用第三方库时的一些特定问题。这些库的未记录行为是,在某些情况下,它在某些条件下抛出异常。最初的问题来自这样一个事实,即即使我们“处理”了错误情况,库也抛出了异常 第二:调试时发现如下情况:
1 if (someVariable)
2 {
3 someCode();
4 someOtherCode();
5 throw someExceptionPassedFromTheThirdPartyLibrary;
6 }
7 somethingElse();
调试器在第1行停止,someVariable为false,跳过,调试器正在第5行等待。这里我做了第一个错误的假设,就是我的异常是从这里抛出的
第三:我开始做实验。“someVariable”始终为false,但有时调试器从第1行跳到第7行,有时从第1行跳到第5行。我决定使用反汇编程序
第四:我无法理解反汇编代码的行为,它使我的想法根深蒂固,即if语句的行为不正确。此外,我还发现了一篇文章“http://stackoverflow.com/questions/6054987/if-statement-appears-to-be-evaluating-even-when-condition-evaluates-to-false“[确认JIT错误]这一次对我没有帮助
好的,我认为在一些额外的背景知识之后,是时候解释一下我的代码中到底发生了什么
一般来说,在我的情况下,“if”语句的行为是正确的。当我学到更多关于汇编程序和现代处理器体系结构的知识时,我明白了这一点
53: if (errorCode32.Equals(errorTimeout) == false)
000000f2 lea ecx,[ebp-54h]
000000f5 mov edx,dword ptr [ebp-58h]
000000f8 call 699EB198
000000fd mov dword ptr [ebp-68h],eax
00000100 movzx eax,byte ptr [ebp-68h]
00000104 mov dword ptr [ebp-48h],eax
00000107 cmp dword ptr [ebp-48h],0
0000010b jne 00000134
54: {
0000010d nop
55: System.Console.Out.WriteLine("aaa");
0000010e call 69538768
00000113 mov dword ptr [ebp+FFFFFF7Ch],eax
00000119 mov edx,dword ptr ds:[0302CE30h]
0000011f mov ecx,dword ptr [ebp+FFFFFF7Ch]
00000125 mov eax,dword ptr [ecx]
00000127 call dword ptr [eax+000000D8h]
0000012d nop
56: return;
0000012e nop
0000012f jmp 00000287
00000134 mov eax,dword ptr ds:[0302CE34h]
0000013a mov dword ptr [ebp-6Ch],eax
0000013d mov edx,5
00000142 mov ecx,6EDE3FBEh
00000147 call FA68D488
0000014c mov dword ptr [ebp-70h],eax
57: }
偏移量00000104-0000010b处指令的执行由处理器体系结构优化(可能发生跳转预测,或其他一些核心处理器优化)。所以,处理器不调用三条指令,而是一步完成所有操作。因为00000107中应该比较的值不相等,所以处理器跳到00000134。在这一点上,我无法理解这里到底发生了什么,所以我假设它只是执行“return”指令。事实很简单——“从if返回”指令并不像我想象的那样位于00000134,但指令更大——位于0000012f,这只是简单的无条件跳转
当我理解这一点时,我知道这段代码的行为是正确的。所以我又搬到了C#,我发现了一些让我感到羞愧的事情。因为当我再次调试代码时,我发现它的行为是这样的:
1 if (someVariable)
2 {
3 someCode();
4 someOtherCode();
5 throw someExceptionPassedFromTheThirdPartyLibrary;
6 }
7 somethingElse();
断点位于1,F10
当前线路指示器位于5,按F10
当前线路指示器位于7,按F10。。。等等
所以我知道调试器会在最后一条“if”指令中执行,但不会执行。这是一个bug,但不是在“if”处理中,而是仅在VS调试器中。此外,这个bug并不重要,因为它实际上只是一个演示,对调试的代码没有任何影响。Adam-这是我首先检查的。Pl
53: if (errorCode32.Equals(errorTimeout) == false)
000000f2 lea ecx,[ebp-54h]
000000f5 mov edx,dword ptr [ebp-58h]
000000f8 call 699EB198
000000fd mov dword ptr [ebp-68h],eax
00000100 movzx eax,byte ptr [ebp-68h]
00000104 mov dword ptr [ebp-48h],eax
00000107 cmp dword ptr [ebp-48h],0
0000010b jne 00000134
54: {
0000010d nop
55: System.Console.Out.WriteLine("aaa");
0000010e call 69538768
00000113 mov dword ptr [ebp+FFFFFF7Ch],eax
00000119 mov edx,dword ptr ds:[0302CE30h]
0000011f mov ecx,dword ptr [ebp+FFFFFF7Ch]
00000125 mov eax,dword ptr [ecx]
00000127 call dword ptr [eax+000000D8h]
0000012d nop
56: return;
0000012e nop
0000012f jmp 00000287
00000134 mov eax,dword ptr ds:[0302CE34h]
0000013a mov dword ptr [ebp-6Ch],eax
0000013d mov edx,5
00000142 mov ecx,6EDE3FBEh
00000147 call FA68D488
0000014c mov dword ptr [ebp-70h],eax
57: }
1 if (someVariable)
2 {
3 someCode();
4 someOtherCode();
5 throw someExceptionPassedFromTheThirdPartyLibrary;
6 }
7 somethingElse();