20

次のような 2 つの Int32 を含む Int64 があります。

[StructLayout(LayoutKind.Explicit)]
public struct PackedInt64
{
    [FieldOffset(0)]
    public Int64 All;
    [FieldOffset(0)]
    public Int32 First;
    [FieldOffset(4)]
    public Int32 Second;
}

ここで、コンストラクターが必要です ( allfirst 、および second用)。ただし、構造体では、コンストラクターを終了する前にすべてのフィールドを割り当てる必要があります。allコンストラクターを考えてみましょう。

public PackedInt64(Int64 all)
{
    this.First = 0;
    this.Second = 0;
    Thread.MemoryBarrier();
    this.All = all;
}

コンストラクターで最後に割り当てられていることを絶対に確認してthis.All、コンパイラーの最適化や CPU での命令の並べ替えが発生した場合にフィールドの半分以上が上書きされないようにする必要があります。

Thread.MemoryBarrier()十分ですか?それは最良の選択肢ですか?

4

4 に答える 4

4

MemoryBarrier再注文を防ぎますが、このコードはまだ壊れています。

LayoutKind.Explicitまた、オブジェクトがアンマネージ コードに渡されるとFieldOffsetAttribute、オブジェクトのメモリ レイアウトに影響を与えると記載されています。C との相互運用には使用できますが、 C のエミュレートには使用できません。unionunion

テストしたプラットフォームで現在期待どおりに動作していても、引き続き動作するという保証はありません。行われる唯一の保証は、アンマネージ コードとの相互運用のコンテキスト (つまり、p/invoke、COM 相互運用、または C++/CLI it-just-works) です。

移植可能な将来性のある方法でバイトのサブセットを読み取りたい場合は、ビット単位の操作またはバイト配列とBitConverter. 構文がそれほど良くなくても。

于 2013-07-08T13:12:11.430 に答える
2

次のリンクの備考セクションを確認してください: http://msdn.microsoft.com/en-us/library/system.threading.thread.memorybarrier.aspx

MemoryBarrier()メモリの順序付けが弱いマルチプロセッサ システムでのみ必要であると書かれています。したがって、これは十分なオプションですが、これが最適なオプションであるかどうかは、使用しているシステムによって異なります。

于 2013-07-08T12:48:18.720 に答える