C#keyword固定/不安全的用途是什么?

时间:2014-02-24 07:12:24

标签: c#

C#keyword固定/不安全的用途是什么?

例如,http://www.dotnetperls.com/fixed

using System;

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

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

3 个答案:

答案 0 :(得分:26)

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

fixed逻辑上将变量修复到内存中,因此它不会移动。

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

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

请在此处查看我的问题:C# Copy variables into buffer without creating garbage?原因之一。

答案 1 :(得分:9)

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可能会删除,也可能不会删除,具体取决于明显它看起来不可能违反它们。)

答案 2 :(得分:1)

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

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