//Code that copies the bytes in a loop
与仅使用...相"/>

关于.net:C#不安全/固定代码

关于.net:C#不安全/固定代码

C# Unsafe/Fixed Code

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

考虑这段代码...

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

与仅使用...相比

1
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快得多。

1
2
3
4
5
6
unsafe
{
    BitmapData bmData = bm.LockBits(...)
    byte *bits = (byte*)pixels.ToPointer();
    // Do stuff with bits
}

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


reinterpret_cast样式行为

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

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 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框架的设计者在覆盖问题空间方面做得很好-确保"托管代码"环境可以处理传统(例如C ++)方法使用其不安全的代码/指针可以执行的所有操作。万一不能,如果需要,可以使用不安全/固定的功能。我确定有人举了一个需要不安全代码的示例,但是在实践中似乎很少见,这很重要,不是吗? :)


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


推荐阅读

    linux固定ip命令?

    linux固定ip命令?,地址,系统,信息,网络,服务,命令,网卡,终端,网关,步骤,Linux

    linux命令基础代码?

    linux命令基础代码?,基础,系统,管理,工作,代码,网络,单位,信息,数据,命令,lin

    linux打开代码命令行?

    linux打开代码命令行?,系统,首页,工具,终端,代码,密码,情况,命令,快捷键,窗

    linux克隆代码命令?

    linux克隆代码命令?,系统,代码,文件,命令,目录,源文件,文件夹,路径,目标,表

    linux命令行调试代码?

    linux命令行调试代码?,环境,代码,信息,平台,程序,编辑,版本,步骤,体系结构,

    linux编译源代码命令?

    linux编译源代码命令?,工具,代码,百度,最新,环境,项目,系统,电脑,密码,内核,l

    linux命令提交代码?

    linux命令提交代码?,工作,系统,地址,代码,命令,数据,信息,目录,标准,发行,求

    linux代码同步命令?

    linux代码同步命令?,时间,服务,系统,地址,代码,网络,通信,图片,风险,管理,lin

    linux命令错误代码?

    linux命令错误代码?,系统,密码,电脑,网络,手机,网址,软件,代码,设备,老板,Lin

    linux同步代码命令?

    linux同步代码命令?,时间,系统,通信,网络,标准,图片,服务,代码,线程,单位,Lin

    linux拉取代码命令?

    linux拉取代码命令?,代码,工作,地址,命令,数据,系统,单位,生产,软件,目录,lin

    linux代码对齐命令?

    linux代码对齐命令?,系统,地址,标准,信息,对比,名称,代码,命令,文件,工作,lin

    linux命令运行代码?

    linux命令运行代码?,代码,单位,系统,环境,连续,保险,工具,命令,文件,音乐,Lin

    搭建linux命令行代码?

    搭建linux命令行代码?,系统,软件,工作,名字,服务,代码,地址,环境,管理,密码,l

    linux查看命令代码?

    linux查看命令代码?,系统,信息,代码,名称,命令,设备,数字,第一,软件,管理,在L

    linux删除代码命令行?

    linux删除代码命令行?,系统,代码,命令,文件,不了,环境,档案,名称,目录,文件

    linux命令行代码实现?

    linux命令行代码实现?,标准,代码,管理,网络,地址,工作,命令,网上,环境,名称,

    linux桌面命令代码?

    linux桌面命令代码?,电脑,系统,密码,环境,代码,基础,地址,服务,网上,通讯,lin

    c代码执行linux命令?

    c代码执行linux命令?,系统,工作,标准,情况,代码,环境,设备,命令,函数,指令,li

    linux进入代码行命令?

    linux进入代码行命令?,系统,代码,设备,终端,环境,信息,第一,命令,窗口,模式,