为什么固定大小的缓冲区(数组)必须是不安全的?

假设我想要一个7字节(或3或777)的值类型。

我可以这样定义:

public struct Buffer71 { public byte b0; public byte b1; public byte b2; public byte b3; public byte b4; public byte b5; public byte b6; } 

定义它的一种更简单的方法是使用固定缓冲区

 public struct Buffer72 { public unsafe fixed byte bs[7]; } 

当然第二个定义更简单。 问题在于必须为固定缓冲区提供unsafe关键字。 我知道这是使用指针实现的,因此不安全。

我的问题是为什么它必须是不安全的? 为什么C#不能提供任意常量长度数组并将它们保存为值类型而不是使其成为C#引用类型数组或不安全缓冲区?

因为“固定缓冲区”不是真正的数组。 它是一个自定义值类型,关于用我知道的C#语言生成一个的唯一方法。 CLR无法validation数组的索引是否以安全的方式完成。 代码也不可validation。 最具代表性的演示:

 using System; class Program { static unsafe void Main(string[] args) { var buf = new Buffer72(); Console.WriteLine(buf.bs[8]); Console.ReadLine(); } } public struct Buffer72 { public unsafe fixed byte bs[7]; } 

在此示例中,您可以任意访问堆栈帧。 恶意代码可以使用标准缓冲区溢出注入技术来修补函数返回地址并强制您的代码跳转到任意位置。

是的,这是非常不安全的。