4

この動作は C# で有効になりますか?

public class MyClass
{
    private byte[] data;
    public MyClass()
    {
        this.data = new byte[1024];
    }
    public unsafe byte* getData()
    {
        byte* result = null;
        fixed (byte* dataPtr = data)
        {
            result = dataPtr;
        }
        return result;
    }
}
4

5 に答える 5

17

安全システムをオフにする場合は、プログラムのメモリの安全性を確保する責任があります。あなたがそうするやいなや、あなたはあなたを助ける安全システムなしですべてを安全に行う必要があります。それが「安全でない」という意味です。

C#仕様が明確に述べているように:

移動可能な変数のアドレスは、固定ステートメントを使用してのみ取得でき、そのアドレスは、その固定ステートメントの期間中のみ有効です。

移動可能な変数のアドレスを取得し、それを固定ステートメントの期間後に使用しているため、アドレスは無効になっていますしたがって、あなたは特にあなたがしていることを正確にしないように要求されます。

従わなければならないルールを完全かつ深く理解するまでは、安全でないコードを記述しないでください。仕様の第18章をすべて読むことから始めます。

于 2012-04-09T17:14:29.997 に答える
11

このコードは正常にコンパイルされますが、実行時の問題が発生します。コードは本質的に、ヒープ内の未修正のオブジェクトへのポインターを密輸しています。MyClass型を移動する次の GCはdata参照も一緒に移動し、以前に返された値getDataは正しくない場所を指すようになります。

var obj = new MyClass();
unsafe byte* pValue = obj.getData();
// Assuming no GC has happened (bad assumption) then this works fine
*pValue = 42;

// Assume a GC has now happened and `obj` moved around in the heap.  The 
// following code is now over writing memory it simply doesn't own
*pValue = 42;

その最後の行により、アプリがクラッシュしstringたり、別の型の値を上書きしたり、初期化されていない配列に値を突っ込んだりして、他の場所で数学の問題を台無しにしたりしましたか? あなたは何もわかってない。最良の結果は、コードがすぐにクラッシュすることです。

于 2012-04-09T16:28:05.307 に答える
1

このコードは機能しません (コンパイルはできますが、実行時に問題が発生します)。固定領域が終了すると、データは固定されなくなります。

于 2012-04-09T16:28:21.450 に答える
0

いいえ、一度fixedブロックを離れると、 の値はresult無効になります (GC が実行されていない場合、偶然にも有効である可能性があります)。

この種の操作を行う適切な方法は、byte[]C# コードを介してアクセスするアンマネージド メモリ内の への参照を持つか、マネージド配列をアンマネージド メモリにコピーすることです。

于 2012-04-09T16:30:10.060 に答える