Rob*_*Rob 2 il reflection.emit windows-8 .net-4.5
我试图通过我们的编译器和带有Windows 8的.NET 4.5来解决问题的根源.我已将其简化为一小段代码,并想知道是否有人对此问题有任何了解.我写了一些C#,它使用反射生成一个显示问题的程序集.C#(在VS2010解决方案中这里https://dl.dropbox.com/u/10931452/sdata.zip)位于本文的底部.它创建了一个类'sdata',并为其添加了一个名为'blank16'的静态字段.然后它创建一个静态构造函数来初始化该字段.生成的可执行文件将写入c:\ temp\sdatatest.exe.当sdatatest在.NET 4.5下运行时,它会生成:
未处理的异常:System.TypeInitializationException:'sdata'的类型初始值设定项引发异常.---> System.AccessViolationException:尝试读取或写入受保护的内存.这通常表明其他内存已损坏.在sdata..cctor()---内部异常堆栈跟踪结束---在sdata.main()
在安装了.NET 4.5的Windows 7上运行时,它会运行.当在早期的.NET框架上运行时,它也会运行 - 并且已经运行了十年.
产生的IL看起来有效:
JITed x86代码看起来也非常有效:
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 ) );
}
}
}
Run Code Online (Sandbox Code Playgroud)
答案是Windows 8更改了.sdata部分的访问权限:将其设置为只读.如果您使用的是DefineUninitializedData,那么您的代码可能会在Windows 8上中断,并且需要更改.
归档时间: |
|
查看次数: |
528 次 |
最近记录: |