3

実行できるように安全にする必要があるこの安全でないコードがあります。ブロックについては知っていfixedますが、実装方法がわかりません:

    private static unsafe void PrintHex(byte* data, uint len)
    {
        uint ctr;
        string sep;

        if (len > 64)
        {
            len = 64;
        }

        for (ctr = 0; ctr < len; ctr++)
        {
            if (((ctr & 7) == 0) && (ctr != 0))
            {
                sep = "\n";
            }
            else
            {
                sep = "";
            }
            Console.Error.WriteLine("{0}{1:X}", sep, data[ctr]);
        }

        Console.Error.WriteLine("\n\n");

    }
4

2 に答える 2

3

MSDN ページの次の例のように、メソッドを呼び出す前にポインターを「修正」または「固定」するのは、呼び出し元のコードの責任ですfixed

class Point
{ 
    public int x, y; 
}

class FixedTest 
{
    // Unsafe method: takes a pointer to an int.
    unsafe static void SquarePtrParam (int* p) 
    {
        *p *= *p;
    }

    unsafe static void Main() 
    {
        Point pt = new Point();
        pt.x = 5;
        pt.y = 6;

        // Pin pt in place:
        fixed (int* p = &pt.x) 
        {
            SquarePtrParam(p);
        }

        // pt now unpinned
        Console.WriteLine ("{0} {1}", pt.x, pt.y);
    }
}

fixed ステートメントは、マネージド変数へのポインターを設定し、ステートメントの実行中にその変数を "固定" します。ガベージ コレクションによって変数が予期せず再配置される可能性があるため、fixed がなければ、移動可能なマネージド変数へのポインターはほとんど役に立ちません。C# コンパイラでは、fixed ステートメント内のマネージド変数にポインターを割り当てることしかできません。

于 2012-06-15T02:02:20.257 に答える
3

実行できるように安全にする必要があるこの安全でないコードがあります。

byte*a (またはその他のポインター型)を使用するコードは、定義上、C# では常に "安全でない" コードになります。API を完全に変更しない限り、これを「安全な」コードに変換する方法はありません。

そうは言っても、これは次のように管理されたバイト配列で機能する可能性があります。

private static void PrintHex(byte[] data, uint len)
{
    uint ctr;
    string sep;

    if (len > 64)
    {
        len = 64;
    }

    for (ctr = 0; ctr < len && ctr < data.Length; ctr++)
    {
        if (((ctr & 7) == 0) && (ctr != 0))
        {
            sep = "\n";
        }
        else
        {
            sep = "";
        }
        Console.Error.WriteLine("{0}{1:X}", sep, data[ctr]);
    }

    Console.Error.WriteLine("\n\n");
}

これは、「安全な」マネージド アレイ ( byte[]) と同じように機能します。

また、「len」が単なる配列の長さである場合、ポインターとは異なり、マネージ配列にはその長さが含まれるため、その引数を完全に削除できます。

private static void PrintHex(byte[] data)
{
    for (int ctr = 0; ctr < 64 && ctr < data.Length; ctr++)
    {
        string sep;
        if (((ctr & 7) == 0) && (ctr != 0))
        {
            sep = "\n";
        }
        else
        {
            sep = "";
        }
        Console.Error.WriteLine("{0}{1:X}", sep, data[ctr]);
    }

    Console.Error.WriteLine("\n\n");
}
于 2012-06-15T02:13:24.640 に答える