Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I think my team found a bug in 64bit compiler, can others either confirm or tell my why this is correct?

Tags:

c#

.net

debugging

I have a simple clean room example of this possible bug.

   static void Main(string[] args)
    {
        bool MyFalse = false;

        if (MyFalse)
        {
            throw new Exception();
        }
        try
        {
            int i = 0;
        }
        catch (Exception e)
        {
            Console.Write(e);
        }

        Console.Read();
    }

If compiled in x64 or AnyCPU (when prefer 32bit is set to false in VS2012) the if you put a breakpoint in the if block, it is always hit.

We tried it in VS2012, VS2010 and VS2008 and they all fired the if block when compiled in 64bit, yet in 32bit it does not fire the if block.

We looked at the IL for 32 bit and 64 bit versions and they look the same.

We found this in production code because the if block was being ran and the exception was being thrown no matter what the value of the boolean variable, though in the simple example we cannot seem to throw the exception, it is happening in production code.

Since it is happening in production code, it is not just a debugger issue.

Very strange behavior, but seems to not be acutally running any code in the if block. Developer jumped the gun in assuming that was the exception he was seeing.

(All debugging is in debug mode - production is in release)

If the throw is commented out - the if block is not reached.

like image 635
saunderl Avatar asked May 03 '13 18:05

saunderl


1 Answers

Okay, I see it. This indeed goes wrong in the Debug build for the 64-bit debugger. The key is to set the breakpoint exactly on the if() statement and then to start stepping. It will look like the throw statement is getting executed. But it that doesn't actually happen, actual code execution is proper.

To see what is happening, have it step into the throw statement line. Then use Debug + Disassembly to see where it is actually located. On my machine it looks like this:

       if (MyFalse)
00000040  movzx       ecx,byte ptr [rbp+8] 
00000044  xor         eax,eax 
00000046  test        ecx,ecx 
00000048  sete        al 
0000004b  mov         dword ptr [rbp+1Ch],eax 
0000004e  movzx       eax,byte ptr [rbp+1Ch] 
00000052  mov         byte ptr [rbp+18h],al 
00000055  movzx       eax,byte ptr [rbp+18h] 
00000059  test        eax,eax 
0000005b  jne         0000000000000088            // <=== Note this jump
        {
0000005d  nop 
            throw new Exception();
0000005e  lea         rcx,[5B848928h] 
00000065  call        000000005F65E9E0 
0000006a  mov         qword ptr [rbp+20h],rax 
0000006e  mov         rax,qword ptr [rbp+20h] 
00000072  mov         qword ptr [rbp+28h],rax 
00000076  mov         rcx,qword ptr [rbp+28h] 
0000007a  call        000000005BE4A5D0 
0000007f  mov         rcx,qword ptr [rbp+28h] 
00000083  call        000000005F73E36C 
00000088  nop                                     // <=== yellow arrow here
        }
        try
        {
00000089  nop 
            int i = 0;

You can even see it from the way the debugger groups the machine code instructions with the C# statements. Note how the debugger is confused about the NOP at address 0088. It thinks it belongs the compound if() statement. So it puts the yellow highlight inside the block. But the program has actually taken the jump at address 005b and has skipped the throw statement (addresses 005e through 0083).

Not so sure where to lay the blame on this one, can't blame the C# compiler or the PDB file since this operates correctly in 32-bit mode. It smells like a jitter problem, notable is that the x86 jitter doesn't generate the NOP instruction. You could also make the case that the jitter should have generated the JNE instruction to jump to address 0089. These are but guesses, you can get a real answer at connect.microsoft.com

Just keep this quirk in mind until you hear back or we all get an update in a service pack. The code is actually executing correctly so you only suffer a mild case of bewilderment.

like image 72
Hans Passant Avatar answered Sep 20 '22 07:09

Hans Passant