首页 > 解决方案 > 不安全的方法在没有 /unsafe 的情况下无法重写

问题描述

我有一些用不安全代码编写的代码。有人可以帮我将其转换为正常的托管代码吗?我不知道该怎么做,因为我不明白它实际上在做什么。请告诉我这里发生了什么。

public byte[] GetRowData(int row)
{
    var buffer = new byte[Cols * 6];

    unsafe
    {
        fixed (byte* lpData = buffer, lpTile = &Data[row * Cols * 6])
        {
            var lpD = lpData;
            var lpT = lpTile;

            for (var i = 0; i < Cols; i++, lpD += 6, lpT += 6)
            {
                lpD[0] = lpT[1];
                lpD[1] = lpT[0];

                lpD[2] = lpT[3];
                lpD[3] = lpT[2];

                lpD[4] = lpT[5];
                lpD[5] = lpT[4];
            }
        }
    }

    return buffer;
}

标签: c#

解决方案


指针。它们可以说是最基本的编码工具。它们也可以说是最危险的编码工具。我和他们一起工作过,他们就像“杂耍手榴弹”

.NET 开发人员尽了最大的努力,因此您不必处理它们。而且默认情况下确实无法处理它们。如果您确实需要处理它们,则必须使用不安全的代码。unsafe 允许使用该字节指针byte*

fixed是对 GarbageCollector 的提示:“作为工作的一部分,不要将它从内存位置移走。你会弄乱我的代码。”

编辑:

代码有很多错误和奇怪之处,它需要一个注释才能弄清楚它在做什么。所以你的困惑我希望我会尝试用评论来解释它:

/*The function signature. row is the only data he does not get from a global source. Because of course he get's half the input from global sources, otherwise it would not be hard enough to read!
It seems to do a combined copy and swap operation. And in batches of 6 elements, for some reason*/
public byte[] GetRowData(int row)
{
    //He creates a managed array. It's size is a external value called "Cols" times 6. I hope that at least Cols is a constant, but I doubt it.
    //This is also the output variable. Later known as lpData and lpD.
    var buffer = new byte[Cols * 6];

    //He enters unsafe code, to do his pointer shenanigans.
    unsafe
    {
        //he gets a pointer to the start of the buffer (lpData)
        //he gets a pointer to whatever is in "row * Cols * 6" of the global Data Collection. So this is the part where he actually retrieves the INPUT, based on the argument he gave this function.
        //If Data[row * Cols * 6] is smaler then Cols * 6/buffer.lenght, he already fucked up.
        //He also tells the GC to not optimize those around the memory space. He needs nobody else doing stuff in that area.
        fixed (byte* lpData = buffer, lpTile = &Data[row * Cols * 6])
        {
            //Indexing in arrays with pointers is done with some Pointer Arythmetic: Start Pointer + Index times type width - that is the memory adress you write at.
            //This is defintely the part where most people messed up with pointers. Also the only way to do it. And why the .NET Array will do this for you only after sanity checks on the index.
            //He makes local copies of the pointers, becaus he will do some of the Arithmethic himself - but not all of it
            var lpD = lpData;
            var lpT = lpTile;

            //A for loop. i is jsut your normal running variable to control how many itterations there will be.
            //each itteration he will also count lpD and lpT up by 6, to get the next "batch" of elements.
            for (var i = 0; i < Cols; i++, lpD += 6, lpT += 6)
            {
                //He processes the batch of 6 elements. He copies 6 element from input to output, while also swapping the odd and even elements.
                //Mathwise those indexers work out to: Pointer of the array start + i*6 + stated index * element width
                lpD[0] = lpT[1];
                lpD[1] = lpT[0];

                lpD[2] = lpT[3];
                lpD[3] = lpT[2];

                lpD[4] = lpT[5];
                lpD[5] = lpT[4];
            }
        }
    }

    //We are back out of unsafe code, the pointers have all gone out of scope and he returns whatever he created there in input, from whatever was in Data[row * Cols * 6]
    return buffer;
}

要弄清楚这应该做什么,我需要知道元素的Data外观。


推荐阅读