Законно ли использовать LayoutKind.Explicit, чтобы обойти использование "небезопасных" указателей?
У меня есть код, который выполняет XOR для блоков данных с использованием указателей, что быстро, но я хотел бы избавиться от "небезопасного" требования к сборке. Если я изменю его на использование LayoutKind.Explicit и наложу "ulong[]" поверх "byte[]", я в основном делаю то же самое, что и с указателями, но это кажется столь же опасным. Основное различие между этими двумя заключается в том, что "безопасная" версия составляет примерно половину скорости "небезопасной" версии.
Является ли это законным способом обойти "небезопасную" сборку, или доступ к байту [] 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 ответ
Является ли это законным способом обойти "небезопасную" сборку, или доступ к байту [] 1 байт за раз является единственным законным способом сделать это безопасным способом?
Это законно, так как 1) работает и 2) может давать правильные результаты.
Конечно, это не обязательно "безопасно", потому что вы можете делать "неприятные" вещи, но это все равно будет функционировать. В этом случае вы определенно нарушаете дух безопасного кода, поскольку вы можете делать вещи, которые не должны быть разрешены в "безопасном" коде, например, эффективно обходить проверку длины массива и вызывать переполнение буфера.
Доступ к массиву по одному элементу за раз больше соответствует духу "безопасного" кода, но бывают случаи, когда такие трюки полезны, так как при необходимости они обеспечивают механизм производительности. Если производительность требуется для вашего конкретного сценария, и обычные механизмы не будут работать адекватно, это может быть способом заставить код "работать" в том смысле, что он соответствует вашим спецификациям (перф. Требованиям), не нарушая безопасные ограничения маркировки. сборка как небезопасная.