29

假设我想要一个 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# 引用类型数组或不安全的缓冲区?

4

1 回答 1

12

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

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];
}

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

是的,这很不安全。

于 2010-05-21T11:39:03.413 回答