Скажем, я хочу иметь тип значения 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];
}
Конечно, второе определение более просто. Проблема связана с небезопасным ключевым словом, которое должно быть обеспечено для фиксированных буферов. Я понимаю, что это реализовано с помощью указателей и следовательно небезопасный.
Мой вопрос состоит в том, почему это должно быть небезопасно? Почему не может C# обеспечивать массивы длины произвольной постоянной и сохранять их как тип значения вместо того, чтобы делать это массивом ссылочного типа C# или небезопасными буферами?
Потому что «фиксированный буфер» не является реальным массивом. Это настраиваемый тип значения, и это единственный известный мне способ его создания на языке 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];
}
В этом примере вы можете произвольно обращаться к кадру стека. Стандартный метод внедрения переполнения буфера будет доступен для вредоносного кода, чтобы исправить адрес возврата функции и заставить ваш код перейти в произвольное место.
Да, это довольно небезопасно.