문제

I have code which does XOR on blocks of data using pointers, which is fast, but I'd like to get rid of the "unsafe" requirement on the assembly. If I change it to use LayoutKind.Explicit and overlay a "ulong[]" on top of a "byte[]", I'm basically doing the same thing as I did with pointers, but it seems to be just as dangerous. The main difference between these two is that the "Safe" version is about 1/2 the speed of the "Unsafe" version.

Is this a legitimate way to get around having an "unsafe" assembly, or is accessing the byte[] 1 byte at a time the only legitimate way to do this in a safe manner?

private unsafe static void UnsafeEncode(
    byte[] buffer, int bufPos, ulong[] vector, int SectionLength, byte vectorIndex)
{
    fixed (byte* p = &buffer[bufPos])
    {
        ulong* pCur = (ulong*)p;
        ulong* pEnd = pCur + SectionLength;
        while (pCur < pEnd)
        {
            *pCur ^= vector[vectorIndex++];
            pCur++;
        }
    }
}

[StructLayout(LayoutKind.Explicit)]
private struct ArrayOverlay
{
    [FieldOffset(0)]
    public byte[] Bytes;
    [FieldOffset(0)]
    public ulong[] Longs;
}

private static void SafeEncode(
    byte[] buffer, int bufPos, ulong[] vector, int SectionLength, byte vectorIndex)
{
    var overlay = new ArrayOverlay { Bytes = buffer };
    int shiftleft = (bufPos & 7) << 3;
    int pos = bufPos >> 3;
    if (shiftleft == 0)
    {
        for (int i = 0; i < SectionLength; i++)
            overlay.Longs[i + pos] ^= vector[vectorIndex++];
    }
    else
    {
        int shiftright = (64 - shiftleft) & 63;
        ulong oldVec = 0;
        for (int i = 0; i < SectionLength; i++)
        {
            var vec = vector[vectorIndex++];
            overlay.Longs[i + pos] ^= (vec << shiftleft) | (oldVec >> shiftright);
            oldVec = vec;
        }
        overlay.Longs[SectionLength + pos] ^= (oldVec >> shiftright);
    }
}
도움이 되었습니까?

해결책

Is this a legitimate way to get around having an "unsafe" assembly, or is accessing the byte[] 1 byte at a time the only legitimate way to do this in a safe manner?

This is legitimate, in that it 1) works, and 2) can produce the correct results.

Granted, it's not necessarily "safe" in that you can do things that are "nasty" by doing this, but it will still function. You are definitely violating the spirit of safe code in this case, as you can do things that shouldn't be allowed in "safe" code, such as effectively bypass array length checking and cause buffer overruns.

Accessing the array one element at a time is more in the spirit of "safe" code, but there are times when using tricks like this is valuable, as it provides a mechanism for performance when required. If performance is required for your specific scenario, and the normal mechanisms will not perform adequately, this may be a way to make code that "works" in that it meets your specifications (the perf. requirements) without violating the safe constraints of marking an assembly as unsafe.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top