【问题标题】:Windows 8, .NET 4.5 DefineUninitializedData issueWindows 8、.NET 4.5 DefineUninitializedData 问题
【发布时间】:2012-11-24 13:04:54
【问题描述】:

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

未处理的异常: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 ) );
        }
    }
}

【问题讨论】:

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

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


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2013-11-11
    • 2013-04-18
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多