bma*_*ini 44 c# compiler-optimization
我遇到了代码中的错误,只有在启用了优化的情况下构建代码时才会重现.我制作了一个控制台应用程序来复制测试逻辑(下面的代码).你会看到,当启用优化时,'value'在执行这个无效逻辑后变为null:
if ((value == null || value == new string[0]) == false)
Run Code Online (Sandbox Code Playgroud)
修复是直截了当的,并在违规代码下方注释掉.但是......我更担心的是我可能遇到了汇编程序中的错误,或者其他人可能会解释为什么将值设置为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);
//}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
正常输出应该是:
Pre-check Value is: System.String[]
Post-check Value is: System.String[]
Key is: blah
Value is: System.String[]
Run Code Online (Sandbox Code Playgroud)
越野车的输出是:
Pre-check Value is: System.String[]
Post-check Value is:
Key is: blah
Value is:
Run Code Online (Sandbox Code Playgroud)
我的Env是运行带有.NET 3.5 SP1的Windows Server 2003 R2的VM.使用VS2008 Team System.
谢谢,
布赖恩
Han*_*ant 45
是的,你的表达式致命地混淆了JIT优化器.生成的机器代码如下所示:
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()
Run Code Online (Sandbox Code Playgroud)
错误发生在地址41,优化器得出结论,值将始终为null,因此它直接将null传递给String.Concat().
为了比较,这是关闭JIT优化时生成的代码:
Console.WriteLine("Post-check Value is: " + value);
00000056 mov ecx,dword ptr ds:[03342090h]
0000005c mov edx,dword ptr [ebp-8]
0000005f call 6D77B790
Run Code Online (Sandbox Code Playgroud)
代码被移动了,但请注意,在地址5c,它现在使用局部变量(值)而不是null.
您可以在connect.microsoft.com上报告此错误.解决方法很简单:
if (value != null)
{
Console.WriteLine("Post-check Value is: " + value);
new PrintManager().Print("blah", value);
}
Run Code Online (Sandbox Code Playgroud)