33

C#コードで「安全でない」と「修正された」を実際に使用するのに適した例を誰かが挙げることができますか? 私は以前にそれで遊んだことがありますが、実際にそれの良い使い方を見つけたことはありません.

このコードを検討してください...

fixed (byte* pSrc = src, pDst = dst) {
    //Code that copies the bytes in a loop
}

単純に使用するのに比べて...

Array.Copy(source, target, source.Length);

2 番目は .NET Framework にあるコードで、最初の部分は Microsoft の Web サイトhttp://msdn.microsoft.com/en-us/library/28k1s2k6(VS.80).aspxからコピーしたものです。

組み込みの Array.Copy() は、Unsafe コードを使用するよりも劇的に高速です。これは、2 番目のコードの方が適切に記述されており、1 番目のコードは単なる例にすぎないためかもしれません。それとも、この貧弱な Web 開発者が頭上で何かをいじっているのでしょうか?

4

7 に答える 7

31

これは、アンマネージ コードとの相互運用に役立ちます。アンマネージ関数に渡されるすべてのポインターは、ガベージ コレクターが基になるメモリを再配置するのを防ぐために、固定 (固定) する必要があります。

P/Invoke を使用している場合は、既定のマーシャラーがオブジェクトを固定します。カスタム マーシャリングを実行する必要がある場合や、1 回の P/Invoke 呼び出しの期間よりも長くオブジェクトを固定する必要がある場合があります。

于 2008-09-17T17:22:49.087 に答える
24

Bitmap データを操作するために unsafe ブロックを使用しました。生のポインター アクセスは、SetPixel/GetPixel よりも大幅に高速です。

unsafe
{
    BitmapData bmData = bm.LockBits(...)
    byte *bits = (byte*)pixels.ToPointer();
    // Do stuff with bits
}

「固定」および「安全でない」は通常、相互運用を行う場合、または追加のパフォーマンスが必要な場合に使用されます。すなわち。String.CopyTo() は unsafe を使用し、その実装で固定されています。

于 2008-09-17T17:46:57.373 に答える
8

reinterpret_cast スタイルの動作

少し操作している場合、これは非常に便利です

多くの高性能ハッシュコードの実装では、ハッシュ値に UInt32 を使用します (これにより、シフトが簡単になります)。.Net ではメソッドに Int32 が必要なため、uint を int にすばやく変換する必要があります。実際の値が何であるかは重要ではないため、値のすべてのビットが保持されていることだけが再解釈キャストに必要です。

public static unsafe int UInt32ToInt32Bits(uint x)
{
    return *((int*)(void*)&x);
}

命名はBitConverter.DoubleToInt64Bitsに基づいていることに注意してください。

ハッシュの流れを続けると、スタックベースの構造体を byte* に変換すると、バイトごとのハッシュ関数を簡単に使用できます。

// from the Jenkins one at a time hash function
private static unsafe void Hash(byte* data, int len, ref uint hash)
{
    for (int i = 0; i < len; i++)
    {
        hash += data[i];
        hash += (hash << 10);
        hash ^= (hash >> 6);
    }
}

public unsafe static void HashCombine(ref uint sofar, long data)
{
    byte* dataBytes = (byte*)(void*)&data;
    AddToHash(dataBytes, sizeof(long), ref sofar);
}

unsafe (2.0 以降) でも、stackalloc を使用できます。これは、一時スペースのような小さな可変長配列が必要な高パフォーマンスの状況で非常に役立ちます。

これらの使用法はすべて、「アプリケーションが本当にパフォーマンスを必要とする場合のみ」に固執するため、一般的な使用には不適切ですが、本当に必要な場合もあります。

C スタイルの配列または文字列を取る便利なアンマネージ関数 (多数あります) と相互運用する場合は、fixed が必要です。そのため、パフォーマンス上の理由だけでなく、相互運用シナリオでの正確性の問題もあります。

于 2009-01-28T16:05:27.393 に答える
4

Unsafe は、(たとえば) LockBits を使用して画像からピクセル データをすばやく取得する場合に役立ちます。マネージ API を使用してこれを行うよりも、パフォーマンスが数桁向上します。

于 2008-09-17T17:22:20.303 に答える
3

アドレスがレガシ C DLL に渡されるときに、固定を使用する必要がありました。DLL は関数呼び出し間で内部ポインターを維持していたため、GC がヒープを圧縮して何かを移動した場合、すべての地獄が壊れてしまいます。

于 2008-09-17T17:20:06.190 に答える
1

.NET ランタイム以外の何かにアクセスする場合、安全でないコードが使用されると思います。マネージド コードではありません (ガベージ コレクションなどはありません)。これには、Windows API への生の呼び出しとそのすべてが含まれます。

于 2008-09-17T17:17:32.843 に答える
1

これは、.NET フレームワークの設計者が問題領域をうまくカバーしたことを示しています。つまり、「マネージ コード」環境が、従来の (C++ などの) アプローチが安全でないコード/ポインターで実行できるすべてのことを実行できるようにすることです。できない場合でも、必要に応じて安全でない/修正された機能があります。安全でないコードが必要な例を誰かが持っていると確信していますが、実際にはめったにないようです-それはむしろポイントですよね? :)

于 2008-09-17T17:20:47.123 に答える