windows-8 - Windows 8、.NET 4.5 DefineUninitializedData 问题

标签 windows-8 .net-4.5 reflection.emit il

我试图找出我们的编译器和 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 下的 Windows 8 上运行时,它会生成:

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 看起来有效:

enter image description here

JITed 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 ) );
        }
    }
}

最佳答案

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

关于windows-8 - Windows 8、.NET 4.5 DefineUninitializedData 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13541483/

相关文章:

c# - 通过 Microsoft Web API 端点调用 Web 服务 - asmx?

concurrency - 为什么 ReadOnlyDictionary 不是线程安全的?

c# - Reflect.Emit 动态类型内存爆炸

c# - DynamicAssembly 中的数组边界检查仅在计算堆栈为空时才有效

c# - 软键盘资本初

c# - 如何以编程方式保持自定义设置 Charm 弹出窗口打开?

css - 有没有办法动画到下一个或上一个 -ms-scroll-snap-points-x?

internet-explorer - Windows 8 - IE 无法访问主机文件中列出的站点

.net - MediaCapture Windows 8 桌面 - 照片较暗

.net - 为什么只允许动态方法跳过可见性检查?