6

.NET は、.NET バイト配列が常に適切にアラインされていることを保証しますか? たとえば、安全でないコンテキストのバイト配列をx64のlongとして扱い、データのチャンクをネイティブレジスタサイズで変更するには、これが必要です。

しかし、これまでのところ、CLR がメモリ アクセスが適切に調整されていることを保証するというドキュメントは見つかりませんでした。

4

2 に答える 2

8

いいえ。実際、アレイは x86 ジッターに対して正しく配置されていない可能性があります。特に double[] と long[] の問題です。ガベージ コレクターは、それらが 4 でアラインされることを保証するだけです。これは、double[] の特別なルールを説明しています。 1000 以上の要素があります。LOH 割り当ての通常のルールよりもかなり少なく、85000 バイト以上です。LOH は、Windows ヒープ アライメントの保証に依存し、8 でアライメントされます。これは、x64 ジッターの問題ではありません。

質問をもう少し具体的にすると、バイト配列が問題になることはありません。配列の開始位置に関係なく、バイトは常に位置合わせされます。Microsoft コンパイラでコンパイルされたアンマネージ コードの "long" も問題ではありません。これは 4 バイトであるため、常に既定の GC アライメント ルールに問題なく適合します。x64 モードでも 4 バイトなので問題ありません。

于 2013-03-19T14:42:10.483 に答える
1

.NET オブジェクト (配列が種である) では、ポインターのサイズに基づいて常に整列されます (たとえば、4 バイトまたは 8 バイトの整列)。そのため、オブジェクト ポインターとオブジェクト配列は常に .NET で整列されます。

また、.NET でポインターを逆参照する場合、位置合わせは必要ないことも指摘しておく必要があります。ただし、速度は遅くなります。たとえば、有効な byte* ポインターがあり、それが 8 バイト以上の長さのデータを指している場合、それを long* にキャストして値を取得できます。

unsafe
{
    var data = new byte[ 16 ];
    fixed ( byte* dataP = data )
    {
        var misalignedlongP = ( long* ) ( dataP + 3 );
        long value = *misalignedlongP;
    }
}

.NET のソース コードを読むと、Microsoft が整合性を考慮している場合とそうでない場合があることがわかります。例は内部System.Buffer.Memmoveメソッドです ( https://referencesource.microsoft.com/#mscorlib/system/buffer.cs,c2ca91c0d34a8f86を参照)。そのメソッドには、いくつかの場所でアラインメント チェックを行わずに byte* を long にキャストするコード パスがあり、呼び出し元のメソッドもアラインメントをチェックしません。

于 2017-11-06T15:31:10.513 に答える