Windows 8 Windows 8、.NET 4.5定义未初始化数据问题

Windows 8 Windows 8、.NET 4.5定义未初始化数据问题,windows-8,.net-4.5,reflection.emit,il,Windows 8,.net 4.5,Reflection.emit,Il,我正试图弄清我们的编译器和.NET4.5与Windows8之间的问题的根源。我将其简化为一小段代码,并想知道是否有人对此问题有任何见解。我已经编写了一些C#,它使用反射生成一个显示问题的程序集。C#is(在这里的VS2010解决方案中)位于本文的底部。它创建一个类“sdata”,并向其中添加一个名为“blank16”的静态字段。然后,它创建一个初始化此字段的静态构造函数。生成的可执行文件将写入c:\temp\sdatatest.exe。在.NET 4.5下的Windows 8上运行sdatate

我正试图弄清我们的编译器和.NET4.5与Windows8之间的问题的根源。我将其简化为一小段代码,并想知道是否有人对此问题有任何见解。我已经编写了一些C#,它使用反射生成一个显示问题的程序集。C#is(在这里的VS2010解决方案中)位于本文的底部。它创建一个类“sdata”,并向其中添加一个名为“blank16”的静态字段。然后,它创建一个初始化此字段的静态构造函数。生成的可执行文件将写入c:\temp\sdatatest.exe。在.NET 4.5下的Windows 8上运行sdatatest时,它会生成:

未处理的异常:System.TypeInitializationException:类型 “sdata”的初始值设定项引发异常。--> System.AccessViolationException:尝试读或写保护 记忆。这通常表示其他内存已损坏。在 sdata..cctor()---内部异常堆栈跟踪的结束---at sdata.main()

在安装了.NET 4.5的Windows 7上运行时,它会运行。在早期的.NET框架上运行时,它也可以运行,并且已经运行了十年

生成的IL看起来有效:

JITed x86代码看起来也非常有效:

edi的值看起来可疑地像是加载的可执行文件中的一个位置,而不是托管内存空间中的一个位置。如果它是只读的,则可以解释访问冲突。为什么在Windows8上会发生这种变化

C#生产sdatatest组件:

using System;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;

namespace sdata
{
    class Program
    {
        static void Main( string[] args )
        {
            AssemblyName name = new AssemblyName( );
            name.Name = "sdatatest.exe";
            string exepath = "c:\\temp\\" + name.Name;
            name.CodeBase = "file:://" + exepath;
            AssemblyBuilder ass_bldr = Thread.GetDomain( ).DefineDynamicAssembly( name, AssemblyBuilderAccess.RunAndSave, Path.GetDirectoryName( exepath ));
            ModuleBuilder module_bldr = ass_bldr.DefineDynamicModule( Path.GetFileName( exepath ), Path.GetFileName( exepath ), true );
            TypeBuilder tb = module_bldr.DefineType( "sdata", TypeAttributes.Public | TypeAttributes.AnsiClass );
            TypeBuilder sixteen = module_bldr.DefineType( "sixteen", TypeAttributes.Sealed, typeof( ValueType ), PackingSize.Size8, 16 ); // value type of size 16
            Type t16 = sixteen.CreateType( );
            var fb = tb.DefineUninitializedData( "blank16", 16, FieldAttributes.Public | FieldAttributes.Static );
            ConstructorBuilder cons = tb.DefineConstructor( MethodAttributes.Static, CallingConventions.Standard, Type.EmptyTypes ); // ..cctor
            var il = cons.GetILGenerator( );
            il.BeginScope( );
            il.Emit( OpCodes.Ldsflda, fb );
            il.Emit( OpCodes.Ldc_I4, 0 );
            il.Emit( OpCodes.Ldc_I4, 16 );
            il.Emit( OpCodes.Initblk );
            il.Emit( OpCodes.Ret );
            il.EndScope( );
            MethodBuilder mb = tb.DefineMethod( "main", MethodAttributes.Static | MethodAttributes.Public );
            il = mb.GetILGenerator( );
            il.BeginScope( );
            il.Emit( OpCodes.Ldsflda, fb );
            il.Emit( OpCodes.Pop );
            il.Emit( OpCodes.Ret );
            il.EndScope( );
            tb.CreateType( );
            ass_bldr.SetEntryPoint( mb );
            ass_bldr.Save( Path.GetFileName( exepath ) );
        }
    }
}

答案是Windows 8更改了.sdata部分的访问权限:使其成为只读。如果您使用的是DefineUninitializedData,那么您的代码可能会在Windows 8上中断,需要更改。

我假设您尝试在生成的程序集上运行PEVerify?ModuleBuilder.CreateGlobalFunctions()在您的代码中丢失,使用DefineUninitializedData()时需要它。如果这没有帮助,那么在connect.microsoft.comModuleBuilder.CreateGlobalFunctions()上提交一份错误报告。很遗憾,这没有任何区别。PEVerify很有趣。它抱怨大会名称中有“.”。所以我修复了它,现在它显示:[IL]:错误:[C:\temp\sdatatest.exe:sdata::.cctor][offset 0x00000000]无法修改基于映像的(RVA)静态[IL]:错误:[C:\temp\sdatatest.exe:sdata::main][offset 0x00000000]无法修改基于映像的(RVA)静态哪种类型表明了这个问题,但没有说明为什么a)它已经工作了10年b)如果它只提供未初始化的只读数据,那么定义InInitializedData的目的是什么…@Rob你能给我发电子邮件到Microsoft.com的netfx45compat吗?我想帮你看看。尊敬的Varun Gupta(Microsoft.NET Framework兼容性团队)