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;
}
}
}
}
为什么我需要首先修复它?感谢
答案 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时,我们告诉框架不要重定位地址指针所指向的对象。