繁体   English   中英

C#不安全/固定代码

[英]C# Unsafe/Fixed Code

有人可以举例说明在C#代码中实际使用“不安全”和“固定”的好时机吗? 我以前玩过它,但从未真正找到好的用途。

考虑这段代码...

fixed (byte* pSrc = src, pDst = dst) {
    //Code that copies the bytes in a loop
}

与仅使用...相比

Array.Copy(source, target, source.Length);

第二个是.NET Framework中的代码,第一个是从Microsoft网站http://msdn.microsoft.com/zh-cn/library/28k1s2k6(VS.80).aspx复制的代码的一部分。

内置的Array.Copy()比使用Unsafe代码要快得多。 这可能只是因为第二个代码编写得更好,第一个仅仅是示例,但是您实际上需要在哪种情况下使用Unsafe / Fixed代码? 还是这位可怜的Web开发人员搞砸了他头上的东西?

对于与非托管代码互操作很有用。 传递给非托管函数的所有指针都必须固定(也称为固定),以防止垃圾回收器重新定位基础内存。

如果您使用的是P / Invoke,则默认的编组器将为您固定对象。 有时有必要执行自定义编组,有时有必要将对象固定的时间长于单个P / Invoke调用的持续时间。

我使用了不安全的块来操作位图数据。 原始指针访问比SetPixel / GetPixel快得多。

unsafe
{
    BitmapData bmData = bm.LockBits(...)
    byte *bits = (byte*)pixels.ToPointer();
    // Do stuff with bits
}

在进行互操作或需要额外性能时,通常使用“固定”和“不安全”。 就是 String.CopyTo()在其实现中使用不安全和固定的。

reinterpret_cast样式行为

如果您有点操纵,那么这可能会非常有用

许多高性能哈希码实现使用UInt32作为哈希值(这使转换变得更简单)。 由于.Net需要Int32作为方法,因此您需要将uint快速转换为int。 由于与实际值无关紧要,因此仅保留值中的所有位,都需要重新解释转换。

public static unsafe int UInt32ToInt32Bits(uint x)
{
    return *((int*)(void*)&x);
}

请注意,命名是根据BitConverter.DoubleToInt64Bits建模的

继续使用哈希算法,将基于堆栈的结构转换为字节*,可以轻松使用每字节哈希函数:

// from the Jenkins one at a time hash function
private static unsafe void Hash(byte* data, int len, ref uint hash)
{
    for (int i = 0; i < len; i++)
    {
        hash += data[i];
        hash += (hash << 10);
        hash ^= (hash >> 6);
    }
}

public unsafe static void HashCombine(ref uint sofar, long data)
{
    byte* dataBytes = (byte*)(void*)&data;
    AddToHash(dataBytes, sizeof(long), ref sofar);
}

不安全的(从2.0开始)还允许您使用stackalloc。 这在需要某些小型可变长度数组(例如临时空间)的高性能情况下非常有用。

所有这些用途都将牢牢地存在于“仅当您的应用程序确实需要性能时”,因此在一般用途中不合适,但有时您确实需要它。

当您希望与使用c样式数组或字符串的一些有用的非托管函数(有很多)互操作时,fixed是必需的。 因此,在互操作方案中,这不仅是出于性能原因,而且还出于正确性的原因。

不安全对于(例如)使用LockBits快速从图像中获取像素数据很有用。 使用托管API进行此操作后,性能提高了几个数量级。

当地址传递到旧版C DLL时,我们必须使用固定值。 由于DLL维护了跨函数调用的内部指针,因此,如果GC压缩了堆并四处移动了东西,所有的地狱都会崩溃。

我相信,如果要访问.NET运行时之外的内容,则使用不安全的代码。 它不是托管代码(没有垃圾回收等)。 这包括对Windows API和所有爵士乐的原始调用。

这告诉我.NET框架的设计者在覆盖问题空间方面做得很好-确保“托管代码”环境可以处理传统(例如C ++)方法使用其不安全的代码/指针可以执行的所有操作。 万一不能,如果需要,可以使用不安全/已修复的功能。 我确定有人举了一个需要不安全代码的示例,但在实践中似乎很少见,这很重要,不是吗? :)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM