使用LayoutKind是否合法?明确地避免使用&;unsafe&;指针
本文关键字:指针 unsafe 是否 LayoutKind 使用 | 更新日期: 2023-09-27 18:17:11
我有代码使用指针对数据块进行异或,这是快速的,但我想摆脱对程序集的"不安全"要求。如果我把它改成使用LayoutKind。显式地将"ulong[]"叠加在"byte[]"之上,我基本上是在做与指针相同的事情,但它似乎同样危险。这两种版本的主要区别是"安全"版本的速度大约是"不安全"版本的一半。
这是绕过"不安全"程序集的合法方法吗?还是一次访问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);
}
}
这是绕过"不安全"程序集的合法方法吗?还是一次访问byte[] 1个字节是唯一安全的合法方法?
这是合理的,因为它1)工作,2)可以产生正确的结果。
当然,它不一定是"安全的",因为你可以通过这样做做一些"讨厌的"事情,但它仍然会起作用。在这种情况下,你肯定违反了安全代码的精神,因为你可以做一些在"安全"代码中不应该被允许的事情,比如有效地绕过数组长度检查并导致缓冲区溢出。
一次访问一个数组元素更符合"安全"代码的精神,但有时使用这样的技巧是有价值的,因为它在需要时提供了一种性能机制。如果您的特定场景需要性能,而常规机制不能充分执行,那么这可能是一种使代码"工作"的方法,因为它符合您的规范(性能)。