2

私はコンパイラーとWindows8の.NET4.5で問題の根底に到達しようとしています。私はそれを小さなコードに単純化して、誰かが問題について何か洞察を持っているかどうか疑問に思いました。問題を示すアセンブリを生成するためにリフレクションを使用するC#をいくつか作成しました。C#は(VS2010ソリューションではhttps://dl.dropbox.com/u/10931452/sdata.zip)、この投稿の下部にあります。クラス「sdata」を作成し、「blank16」という静的フィールドを追加します。次に、このフィールドを初期化する静的コンストラクターを作成します。結果の実行可能ファイルはc:\ temp\sdatatest.exeに書き込まれます。sdatatestを.NET4.5のWindows8で実行すると、次のようになります。

未処理の例外:System.TypeInitializationException:「sdata」の型初期化子が例外をスローしました。---> System.AccessViolationException:保護されたメモリの読み取りまたは書き込みを試みました。これは多くの場合、他のメモリが破損していることを示しています。at sdata..cctor()---内部例外スタックトレースの終了--- at sdata.main()

.NET4.5がインストールされたWindows7で実行すると、実行されます。以前の.NETFrameworkで実行すると、それも実行されます–そして10年間実行されています。

生成されたILは有効に見えます:

ここに画像の説明を入力してください

JITedx86コードも完全に有効に見えます。

ここに画像の説明を入力してください

ediの値は、管理対象メモリスペースではなく、ロードされた実行可能ファイル内の場所のように疑わしく見えます。読み取り専用の場合は、アクセス違反を説明します。しかし、なぜこれがWindows 8で変更されるのでしょうか?

sdatatestアセンブリを生成するためのC#:

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

1 に答える 1

5

答えは、Windows 8が.sdataセクションのアクセス権を変更し、読み取り専用にしたことです。DefineUninitializedDataを使用している場合、コードはWindows 8で壊れてしまう可能性があり、変更する必要があります。

于 2012-12-10T21:41:31.580 に答える