Cole Tobin
Cole Tobin

Reputation: 9427

Making a block of "unsafe" code "safe"

I have this unsafe code that I need to make safe so it can execute. I know about the fixed block, but I don't know how to implement it:

    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");

    }

Upvotes: 3

Views: 2968

Answers (2)

Mitch Wheat
Mitch Wheat

Reputation: 300579

It's the responsibility of the calling code to 'fix' or 'pin' the pointer before calling your method, as in this example from the MSDN page for 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);
    }
}

The fixed statement sets a pointer to a managed variable and "pins" that variable during the execution of statement. Without fixed, pointers to movable managed variables would be of little use since garbage collection could relocate the variables unpredictably. The C# compiler only lets you assign a pointer to a managed variable in a fixed statement.

Upvotes: 3

Reed Copsey
Reed Copsey

Reputation: 564451

I have this unsafe code that I need to make safe so it can execute.

Any code which use a byte* (or any other pointer type), by definition, will always be "unsafe" code in C#. There is no way to convert this to "safe" code without completely changing the API.

That being said, this could work on a managed byte array like so:

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");
}

This will work the same way off a "safe" managed array (byte[]).

Also - if "len" was just the array length, you can eliminate that argument entirely, as managed arrays include their length, unlike a pointer:

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");
}

Upvotes: 3

Related Questions