2012-11-24 81 views
2

我正试图用我们的编译器和.NET 4.5与Windows 8的问题的底部。我简化了它的一小段代码,并想知道如果有人有任何洞察问题。我写了一些使用反射的C#来生成显示问题的程序集。 C#(在VS2010解决方案中,此处为https://dl.dropbox.com/u/10931452/sdata.zip)位于本文的底部。它创建一个类'sdata'并为其添加一个名为'blank16'的静态字段。然后它创建一个静态构造函数来初始化这个字段。生成的可执行文件写入c:\ temp \ sdatatest.exe。当sdatatest在Windows 8下的.NET 4.5中运行它产生:Windows 8,.NET 4.5 DefineUninitializedData问题

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()

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

的IL产生看起来有效:

enter image description here

的JIT编译x86代码看起来完全有效的太:

enter image description here

EDI的值看起来很像一个位置,在加载的可执行而不是在托管的内存空间中,如果它是只读的,则会解释访问冲突。为什么会在Windows 8上进行更改?

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)); 
     } 
    } 
} 
+0

我假设你尝试在生成的程序集上运行PEVerify? – svick

+0

您的代码中缺少ModuleBuilder.CreateGlobalFunctions(),当您使用DefineUninitializedData()时,它是必需的。如果这没有帮助,请在connect.microsoft.com上提交错误报告。 –

+0

ModuleBuilder.CreateGlobalFunctions()没有任何区别(不幸)。 – Rob

回答

5

答案是,Windows 8已经改变了对.SDATA段的访问权限:使它只读。如果您正在使用DefineUninitializedData,那么您的代码可能会在Windows 8上中断,并且需要更改。