2013-06-06 3 views
2

У меня есть код, который делает XOR на блоках данных с помощью указателей, что быстро, но я бы хотел избавиться от «небезопасного» требования к сборке. Если я изменил его на использование LayoutKind.Explicit и наложил «ulong []» поверх «byte []», я в основном делаю то же, что и с указателями, но, похоже, это так же опасно. Основное различие между этими двумя заключается в том, что «безопасная» версия составляет около 1/2 скорости «небезопасной» версии.Допустимо ли использовать LayoutKind.Explicit, чтобы обойти использование «небезопасных» указателей?

Действительно ли это законный способ обхода «небезопасной» сборки или доступ к байту [] 1 байт за один раз - единственный законный способ сделать это безопасным образом?

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

ответ

1

Является ли это законным способом обойти наличие «небезопасных» сборку, или доступ к Byte [] 1 байт в то время, единственный законный способ сделать это безопасным способом?

Это законно, поскольку оно 1) работает и 2) может давать правильные результаты.

Конечно, это не обязательно «безопасно», потому что вы можете делать что-то «противное», делая это, но оно все равно будет функционировать. В этом случае вы определенно нарушаете дух безопасного кода, так как вы можете делать то, что не должно допускаться в «безопасном» коде, например, эффективно обходить проверку длины массива и вызывать переполнение буфера.

Доступ к массиву по одному элементу за один раз более соответствует духу «безопасного» кода, но есть моменты, когда использование трюков, подобных этому, является ценным, так как оно обеспечивает механизм для производительности при необходимости. Если для вашего конкретного сценария требуется производительность, а нормальные механизмы не будут выполняться должным образом, это может быть способ сделать код, который «работает» таким образом, чтобы он соответствовал вашим требованиям (первичным требованиям), не нарушая безопасных ограничений маркировки сборка как небезопасная.