C#“是”的结构类型检查 - 奇.NET 4.0 x86的优化行为 [英] C# 'is' type check on struct - odd .NET 4.0 x86 optimization behavior
问题描述
更新:我提起的与微软连接错误报告,请为它投票!
更新2:微软已标记的bug报告固定
的发布微软18 / 08/2010 17:25 的
这bug会被固定在
运行时的未来版本。我
怕是为时尚早如果
将在服务包或下
主要版本。
块引用>
由于升级到VS2010我得到的'是'关键字一些很奇怪的行为。
下面的程序(test.cs中)当与优化(用于x86)编译时,在调试模式(86)和假编制真实输出。在编译或x64的所有值为anycpu组合给出了预期的结果,真实。
在.NET 3.5编译给出预期结果的所有组合,真实。
我用下面的批处理文件(runtest.bat)来编译和测试使用编译器的.NET架构的各种组合的代码。
修复
- 有其他人看到这些类型的问题在.NET 4.0?
- 有没有其他人看到自己的计算机上的相同的行为,我跑runtests.bat时?
- #@ $ @#$ ??
- 是否有此?
test.cs中
使用系统;
公共类节目
{
公共静态布尔IsGuid(对象的项目)
{
返回产品的Guid;
}
公共静态无效的主要()
{
Console.Write(IsGuid(Guid.NewGuid()));
}
}
runtest.bat
关闭@echo
REM用法:
REM的runTest - 与CSC.EXE x86的.NET 4.0 $ b $运行b REM的runTest 64 - 用CSC.EXE 64 .NET 4.0
REM的runTest V3.5运行 - 与CSC.EXE x86的.NET 3.5
REM的runTest V3.5 64运行 - 与运行CSC .EXE 64 .NET 3.5
组版本= v4.0.30319
组平台=框架
。对于一个%%在(%*)做(
如果%%一个==64(一套平台= Framework64)
如果%%一个==V3.5(集版本V3.5 =)
)
回声编译:%平台%\%版本%\csc.exe
组CSC =C:\Windows\Microsoft.NET\%平台%\%版本% \csc.exe
组做出=%CSC%/ NOLOGO / nowarn:1607 test.cs中
REM CS1607:引用程序集针对不同的处理器
REM如果发生这种情况编译使用csc64
%彩妆%/平台使用csc32 x64或x86:在86
test.exe的
回声= ^> 86
%彩妆%/平台:86 /优化
test.exe的
回声= ^> 86(优化)
%彩妆%/平台:86 /调试
test.exe的
回声= ^> 86(调试)
%彩妆%/平台:86 /调试/优化
test.exe的
回声= ^> 86(调试+优化)
%彩妆%/平台:64
test.exe的
回声= ^> 64
%彩妆%/平台:X64 /优化
test.exe的
回声= ^> 64(优化)
%彩妆%/平台:X64 /调试
test.exe的
回声= ^> 64(调试)
%彩妆%/平台:X64 /调试/优化
test.exe的
回声= ^> 64(调试+优化)
%彩妆%/平台:值为anycpu
test.exe的
回声= ^>值为anycpu
%彩妆%/平台:值为anycpu /优化
test.exe的
回声= ^>值为anycpu(优化)
%彩妆%/平台:值为anycpu /调试
test.exe的
回声= ^>值为anycpu(调试)
%彩妆%/平台:值为anycpu /调试/优化
test.exe的
回声= ^>值为anycpu(调试+优化)
测试结果
在运行runtest.bat我得到我的Win7的X64以下结果安装
> 32的runTest V4.0
编译:Framework\v4.0.30319\csc.exe
错=> 86
错=> 86(优化)
真=> 86(调试)
错=> 86(调试+优化)
真=> 64
真=> 64(优化)
真=> 64(调试)
真=> 64(调试+优化)
真=>值为anycpu
真=>值为anycpu(优化)
真=>值为anycpu(调试)
真=>值为anycpu(调试+优化)
> 64的runTest V4.0
编译:Framework64\v4.0.30319\csc.exe
错=> 86
错=> 86(优化)
真=> 86(调试)
错=> 86(调试+优化)
真=> 64
真=> 64(优化)
真=> 64(调试)
真=> 64(调试+优化)
真=>值为anycpu
真=>值为anycpu(优化)
真=>值为anycpu(调试)
真=>值为anycpu(调试+优化)
> 32的runTest V3.5
编译:Framework\v3.5\csc.exe
真=> 86
真=> 86(优化)
真=> 86(调试)
真=> 86(调试+优化)
真=> 64
真=> 64(优化)
真=> 64(调试)
真=> 64(调试+优化)
真=>值为anycpu
真=>值为anycpu(优化)
真=>值为anycpu(调试)
真=>值为anycpu(调试+优化)
> 64的runTest V3.5
编译:Framework64\v3.5\csc.exe
真=> 86
真=> 86(优化)
真=> 86(调试)
真=> 86(调试+优化)
真=> 64
真=> 64(优化)
真=> 64(调试)
真=> 64(调试+优化)
真=>值为anycpu
真=>值为anycpu(优化)
真=>值为anycpu(调试)
真=>值为anycpu(调试+优化)
TL;博士
解决方案我的工作了失败同样的方式类似的例子:
使用系统;使用System.Runtime.CompilerServices
;
公共类节目{
静态无效的主要(){
Console.Write(验证(Test.Create()));
到Console.ReadLine();
}
//[MethodImpl(MethodImplOptions.NoInlining)
静态布尔验证(IDisposable的项目){
返回产品测试;
}
结构测试:IDisposable的{
公共无效的Dispose(){}
公共静态测试的Create(){返回新测试(); }
}
}
这是一个JIT优化器的bug。不能完全把手指就可以了,它在很大程度上优化了代码。但它看起来对我来说,它会遇到麻烦时,它优化了装箱转换了。非常严重的错误,坦率地说。
此bug已修复,我不能再瑞普它。我目前clrjit.dll的版本是4.0.30319.237日期为5月17日2011年。我不能告诉正是更新修复它。我得到了2011年8月5日的更新clrjit.dll修订235 4月12日的最新安全更新,这将是最早的。
Update: I have filed a bug report with Microsoft Connect, please vote for it!
Update 2: Microsoft have marked the bug report as fixed
Posted by Microsoft on 18/08/2010 at 17:25
This bug will be fixed in a future version of the runtime. I'm afraid it's too early to tell if that will be in a service pack or the next major release.
Since upgrading to VS2010 I'm getting some very strange behavior with the 'is' keyword.
The program below (test.cs) outputs True when compiled in debug mode (for x86) and False when compiled with optimizations on (for x86). Compiling all combinations in x64 or AnyCPU gives the expected result, True.
All combinations of compiling under .NET 3.5 give the expected result, True.
I'm using the batch file below (runtest.bat) to compile and test the code using various combinations of compiler .NET framework.
- Has anyone else seen these kind of problems under .NET 4.0?
- Does everyone else see the same behavior as me on their computer when running runtests.bat?
- #@$@#$??
- Is there a fix for this?
test.cs
using System; public class Program { public static bool IsGuid(object item) { return item is Guid; } public static void Main() { Console.Write(IsGuid(Guid.NewGuid())); } }
runtest.bat
@echo off rem Usage: rem runtest -- runs with csc.exe x86 .NET 4.0 rem runtest 64 -- runs with csc.exe x64 .NET 4.0 rem runtest v3.5 -- runs with csc.exe x86 .NET 3.5 rem runtest v3.5 64 -- runs with csc.exe x64 .NET 3.5 set version=v4.0.30319 set platform=Framework for %%a in (%*) do ( if "%%a" == "64" (set platform=Framework64) if "%%a" == "v3.5" (set version=v3.5) ) echo Compiler: %platform%\%version%\csc.exe set csc="C:\Windows\Microsoft.NET\%platform%\%version%\csc.exe" set make=%csc% /nologo /nowarn:1607 test.cs rem CS1607: Referenced assembly targets a different processor rem This happens if you compile for x64 using csc32, or x86 using csc64 %make% /platform:x86 test.exe echo =^> x86 %make% /platform:x86 /optimize test.exe echo =^> x86 (Optimized) %make% /platform:x86 /debug test.exe echo =^> x86 (Debug) %make% /platform:x86 /debug /optimize test.exe echo =^> x86 (Debug + Optimized) %make% /platform:x64 test.exe echo =^> x64 %make% /platform:x64 /optimize test.exe echo =^> x64 (Optimized) %make% /platform:x64 /debug test.exe echo =^> x64 (Debug) %make% /platform:x64 /debug /optimize test.exe echo =^> x64 (Debug + Optimized) %make% /platform:AnyCPU test.exe echo =^> AnyCPU %make% /platform:AnyCPU /optimize test.exe echo =^> AnyCPU (Optimized) %make% /platform:AnyCPU /debug test.exe echo =^> AnyCPU (Debug) %make% /platform:AnyCPU /debug /optimize test.exe echo =^> AnyCPU (Debug + Optimized)
Test Results
When running the runtest.bat I get the following results on my Win7 x64 install.
> runtest 32 v4.0 Compiler: Framework\v4.0.30319\csc.exe False => x86 False => x86 (Optimized) True => x86 (Debug) False => x86 (Debug + Optimized) True => x64 True => x64 (Optimized) True => x64 (Debug) True => x64 (Debug + Optimized) True => AnyCPU True => AnyCPU (Optimized) True => AnyCPU (Debug) True => AnyCPU (Debug + Optimized) > runtest 64 v4.0 Compiler: Framework64\v4.0.30319\csc.exe False => x86 False => x86 (Optimized) True => x86 (Debug) False => x86 (Debug + Optimized) True => x64 True => x64 (Optimized) True => x64 (Debug) True => x64 (Debug + Optimized) True => AnyCPU True => AnyCPU (Optimized) True => AnyCPU (Debug) True => AnyCPU (Debug + Optimized) > runtest 32 v3.5 Compiler: Framework\v3.5\csc.exe True => x86 True => x86 (Optimized) True => x86 (Debug) True => x86 (Debug + Optimized) True => x64 True => x64 (Optimized) True => x64 (Debug) True => x64 (Debug + Optimized) True => AnyCPU True => AnyCPU (Optimized) True => AnyCPU (Debug) True => AnyCPU (Debug + Optimized) > runtest 64 v3.5 Compiler: Framework64\v3.5\csc.exe True => x86 True => x86 (Optimized) True => x86 (Debug) True => x86 (Debug + Optimized) True => x64 True => x64 (Optimized) True => x64 (Debug) True => x64 (Debug + Optimized) True => AnyCPU True => AnyCPU (Optimized) True => AnyCPU (Debug) True => AnyCPU (Debug + Optimized)
tl;dr
解决方案I worked up a similar example that fails the same way:
using System; using System.Runtime.CompilerServices; public class Program { static void Main() { Console.Write(Verify(Test.Create())); Console.ReadLine(); } //[MethodImpl(MethodImplOptions.NoInlining)] static bool Verify(IDisposable item) { return item is Test; } struct Test : IDisposable { public void Dispose() { } public static Test Create() { return new Test(); } } }
It is a JIT optimizer bug. Can't quite put the finger on it, it optimizes the code heavily. But it looks to me like it gets in trouble when it optimizes the boxing conversion away. Pretty serious bug, frankly.
This bug has been fixed, I can no longer repro it. My current version of clrjit.dll is 4.0.30319.237 dated May 17th 2011. I can't tell exactly what update repaired it. I got a security update on Aug 5th 2011 that updated clrjit.dll to revision 235 with a date of Apr 12, that would be the earliest.
这篇关于C#“是”的结构类型检查 - 奇.NET 4.0 x86的优化行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!