C# 关键字固定/不安全有什么用?

  • 本文关键字:不安全 关键字 c#
  • 更新时间 :
  • 英文 :


C#关键字fixed/ansafe有什么用?

例如,C#固定关键字(不安全)

using System;
class Program
{
unsafe static void Main()
{
fixed (char* value = "sam")
{
char* ptr = value;
while (*ptr != '')
{
Console.WriteLine(*ptr);
++ptr;
}
}
}
}

为什么我首先需要修复它?

C#是托管语言,这意味着内存是自动管理的,即不由您管理。如果您在修改指针指向的内存时没有使用fixed,C#可能已经将变量移动到另一个内存位置,因此您可能正在修改其他内容!

fixed在逻辑上固定内存中的变量,使其不会四处移动。

为什么C#会移动内存中的变量?为了压缩内存,否则,如果不再活动的对象留下了其他对象无法容纳的洞(堆内存碎片),程序将占用更多可用内存。

我在一个为资源受限设备设计的.NET库中广泛使用了fixed,以避免在缓冲区中创建垃圾复制,并发现在其他无法做到这一点的托管语言中非常缺乏这一功能。在托管语言垃圾收集中编写游戏时,通常是最大的瓶颈之一,因此能够不创建它是非常有帮助的!

请看我的问题:C#在不创建垃圾的情况下将变量复制到缓冲区?原因之一。

unsafe是处理指针所必需的。

fixed有两个用途:

  • 它允许您固定数组并获得指向数据的指针
  • unsafe struct字段中使用时,它声明了一个"固定缓冲区",即通过指针而不是常规字段访问的类型中的保留空间块

用一个特定的例子来回答——这里有一些代码用于在任意大小的两个byte[]之间执行语义相等。。。

internal static unsafe  int GetHashCode(byte[] value)
{
unchecked
{
if (value == null) return -1;
int len = value.Length;
if (len == 0) return 0;
int octects = len / 8, spare = len % 8;
int acc = 728271210;
fixed (byte* ptr8 = value)
{
long* ptr64 = (long*)ptr8;
for (int i = 0; i < octects; i++)
{
long val = ptr64[i];
int valHash = (((int)val) ^ ((int)(val >> 32)));
acc = (((acc << 5) + acc) ^ valHash);
}
int offset = len - spare;
while(spare-- != 0)
{
acc = (((acc << 5) + acc) ^ ptr8[offset++]);
}
}
return acc;
}            
}

因此,例如,如果缓冲区是1000个项,通过将其视为一组long,我们现在只进行125次迭代,而不必单独查看所有1000个项。此外,我们完全绕过了任何数组边界检查(JIT可能会删除也可能不会删除,这取决于明显的看起来不可能违反它们)。

Unsafe代码块很少使用。如果您想创建和使用指针,则主要使用它们。此外,不安全块中的任何代码都是CLR无法控制的。就CLR而言,它被认为是不可验证的(来自MSDN)。

现在,当垃圾回收发生时,一些对象可能会被重新定位。当前缀为fixed时,我们告诉框架不要重新定位地址指针指向的对象。

最新更新