Windows 8, .NET 4.5 DefineUninitializedData issue
我正试图弄清我们的编译器和.NET 4.5与Windows8之间的问题。我把它简化为一小段代码,想知道是否有人对这个问题有任何了解。我已经编写了一些C,它使用反射来生成一个显示问题的程序集。C是(在这里的VS2010解决方案https://dl.dropbox.com/u/10931452/sdata.zip)在本文的底部。它创建一个类"sdata",并向它添加一个名为"blank16"的静态字段。然后它创建一个静态构造函数来初始化这个字段。生成的可执行文件将写入C: empsdatatest.exe。当在.NET 4.5下的Windows 8上运行sdatatest时,它会生成:
Unhandled Exception: System.TypeInitializationException: The type
initializer for 'sdata' threw an exception. --->
System.AccessViolationException: Attempted to read or write protected
memory. This is often an indication that other memory is corrupt. at
sdata..cctor() --- End of inner exception stack trace --- at
sdata.main()
在安装了.NET 4.5的Windows 7上运行时,它将运行。当在早期的.NET框架上运行时,它也在运行——并且已经运行了十年。
生成的IL看起来有效:
jited x86代码看起来也完全有效:
edi的值看起来像是加载的可执行文件中的一个位置,而不是托管内存空间中的一个位置,如果它是只读的,这将解释访问冲突。但是,为什么在Windows8上会发生这种变化?
C生产数据测试组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | 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 ) ); } } } |
答案是Windows8已经更改了.sdata部分的访问权限:使其为只读。如果您使用的是DefineUninitializedData,那么您的代码可能会在Windows8上中断,需要更改。