The error only occurs when compilation optimization is enabled.

I encountered an error in the code, which is reproduced only when the code is built with optimizations enabled. I created a console application that replicates the testing logic (code below). You will see that when optimization is turned on, the value "value" becomes zero after this invalid logic is executed:

if ((value == null || value == new string[0]) == false) 

The fix is ​​direct and commented out below the violation code. But ... it bothers me more that I may have encountered an error in assembler or maybe someone has an explanation why the value is getting null.

 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace memory_testing { class Program { sta tic void Main(string[] args) { while(true) { Console.Write("Press any key to start..."); Console.ReadKey(); Console.WriteLine(); PrintManagerUser c = new PrintManagerUser(); c.MyProperty = new string[1]; } } } public class PrintManager { public void Print(string key, object value) { Console.WriteLine("Key is: " + key); Console.WriteLine("Value is: " + value); } } public class PrintManagerUser { public string[] MyProperty { get { return new string[100]; } set { Console.WriteLine("Pre-check Value is: " + value); if ((value == null || value == new string[0]) == false) { Console.WriteLine("Post-check Value is: " + value); new PrintManager().Print("blah", value); } //if (value != null && value.Length > 0) //{ // new PrintManager().Print("blah", value); //} } } } } 

The normal output should be:

 Pre-check Value is: System.String[] Post-check Value is: System.String[] Key is: blah Value is: System.String[] 

Error output:

 Pre-check Value is: System.String[] Post-check Value is: Key is: blah Value is: 



My Env is a virtual machine running Windows Server 2003 R2 with .NET 3.5 SP1. Using VS2008 Team System.

Thank,

Brian

+44
compiler-optimization c #
Jan 25
source share
5 answers

Yes, your expression fatally confuses the JIT optimizer. The generated machine code is as follows:

  if ((value == null || value == new string[0]) == false) 00000027 test esi,esi ; value == null? 00000029 je 00000075 0000002b xor edx,edx ; new string[0] 0000002d mov ecx,6D913BD2h 00000032 call FFD20BC8 00000037 cmp eax,esi ; (value == new string[0]) == false? 00000039 je 00000075 { Console.WriteLine("Post-check Value is: " + value); 0000003b mov ecx,dword ptr ds:[03532090h] ; "Post-check value is: " 00000041 xor edx,edx ; BUGBUG not null! 00000043 call 6D70B7E8 ; String.Concat() 00000048 mov esi,eax ; 0000004a call 6D72BE08 ; get Console.Out 0000004f mov ecx,eax 00000051 mov edx,esi 00000053 mov eax,dword ptr [ecx] 00000055 call dword ptr [eax+000000D8h] ; Console.WriteLine() 

The error occurs at address 41, the optimizer concluded that the value will always be zero, so it directly passes null to String.Concat ().

For comparison, this is the code that is generated when JIT optimization is disabled:

  Console.WriteLine("Post-check Value is: " + value); 00000056 mov ecx,dword ptr ds:[03342090h] 0000005c mov edx,dword ptr [ebp-8] 0000005f call 6D77B790 

The code has been moved, but note that at address 5c it now uses a local variable (value) instead of null.

You can report this error on connect.microsoft.com. The workaround is simple:

  if (value != null) { Console.WriteLine("Post-check Value is: " + value); new PrintManager().Print("blah", value); } 
+45
Jan 25 '10 at 21:46
source share

This bug seems to be fixed in .NET 4 (beta 2). Here's the optimized x86 disassembly for the nobugz bits highlighted above:

  Console.WriteLine("Post-check Value is: " + value); 00000056 mov ecx,dword ptr ds:[033C2090h] 0000005c mov edx,dword ptr [ebp-8] 0000005f call 65D8FE10 

The program also displays the expected result in both optimized and non-optimized modes.

+3
Jan 28 '10 at 14:50
source share
 value == new string[0] 

The above looks like a strange expression to me. You are comparing two string arrays with an equality expression. This will only lead to truth if both point to the same array, which is unlikely. This does not yet explain why this code behaves differently in the optimized version.

+2
Jan 25
source share

I am on x64 and cannot reproduce the problem first. Then I indicated the target as x86, and this happened to me. Back to x64, and he left. Not sure what that means, but I’ve come back and forth several times already.

+1
Jan 25
source share

Of course, it looks like an error, does it reproduce when you change the operands of an operator as follows?

 if (false == (null == value || new string[0] == value)) 
0
Jan 25 '10 at 21:47
source share



All Articles