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

Swa*_*Jat 13 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;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么我需要首先解决它?谢谢

mar*_*mnl 30

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

fixed 在逻辑上将变量固定在内存中,因此它不会移动.

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

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

在这里查看我的问题:C#将变量复制到缓冲区而不创建垃圾?原因之一.

  • “我在为资源受限设备设计的.NET库中广泛使用了固定方法,以避免在将垃圾复制到缓冲区时发现该功能,而在其他托管语言中则严重缺乏此功能,而您无法做到这一点。在使用托管语言编写游戏时,垃圾回收经常最大的瓶颈之一,因此具有不创建它的能力非常有帮助!” ->谢谢,但是对不起,请您详细说明。我似乎明白了,真正固定内存位置是为了提高性能。但是我真的不是...看看如何,如果您对此进行详细说明,将不胜感激! (2认同)
  • 固定内存不会赋予性能使用指针修改内存的能力,在我的情况下,将多个变量复制到缓冲区而不创建垃圾可以在垃圾收集时间成为问题的情况下提供性能,请参阅我的链接问题。 (2认同)

Mar*_*ell 12

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;
        }            
    }
Run Code Online (Sandbox Code Playgroud)

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

  • @Swab.Jat 如果您查看代码,您可以看到它将每个项目作为“长”而不是“字节”进行处理 - 因此每次迭代都会对 8 个字节进行哈希处理。是的,“不安全”通常被用作性能考虑。还有一种情况是您获得指向完全非托管内存的指针(基本上是互操作场景),但这些情况比性能使用要少得多。 (2认同)

dan*_*ish 4

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

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