Тема 24. Небезопасный код и указатели
Небезопасный код
Для обеспечения строгой типизации и безопасности C# по умолчанию не поддерживает арифметику указателей. Однако с помощью ключевого слова unsafe можно определить небезопасный контекст и использовать указатели.
В среде CLR небезопасный код является непроверяемым. Небезопасный код в C# не обязательно представляет опасность. Это просто код, безопасность которого не может быть проверена средой CLR. Поэтому CLR выполнит этот код. При использовании небезопасного кода программисту необходимо обеспечить гарантию того, что он не создаст угрозу безопасности и не вызовет ошибки указателей.
В некоторых случаях небезопасный код может повысить производительность приложения за счет удаления проверок и использование алгоритмов, в которых арифметика указателей даёт преимущества.
Использование небезопасного кода создает угрозу безопасности и стабильной работы.
Указатели
В небезопасном контексте тип может быть типом указателя, типом значения или ссылочным типом - аналогично использованию в языке C++. Объявления типа указателя выполняется одним из следующих способов:
type* identifier;
void* identifier;
Оператор fixed
Оператор fixed задает указатель на управляемую переменную и "закрепляет" эту переменную во время выполнения оператора. Без fixed, указатели на перемещаемые управляемые переменные были бы мало полезны, так как при сборке мусора переменные переносились бы непредсказуемым образом. Компилятор C# позволяет назначить указатель только управляемой переменной в операторе fixed.
unsafe static void TestMethod()
{
// Assume that the following class exists.
//class Point
//{
// public int x;
// public int y;
//}
// Variable pt is a managed variable, subject to garbage collection.
Point pt = new Point();
// Using fixed allows the address of pt members to be taken,
// and "pins" pt so that it is not relocated.
fixed (int* p = &pt.x)
{
*p = 1;
}
}
Ключевое слово stackalloc
Ключевое слово stackalloc используется в небезопасном контексте кода для выделения блока памяти в стеке.
static unsafe void Main()
{
const int arraySize = 20;
int* fib = stackalloc int[arraySize];
int* p = fib;
// The sequence begins with 1, 1.
*p++ = *p++ = 1;
for (int i = 2; i < arraySize; ++i, ++p)
{
// Sum the previous two numbers.
*p = p[-1] + p[-2];
}
for (int i = 0; i < arraySize; ++i)
{
Console.WriteLine(fib[i]);
}
// Keep the console window open in debug mode.
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
Дополнительная литература
Небезопасный код и указатели (Руководство по программированию в C#) https://msdn.microsoft.com/ru-ru/library/t2yzs44b.aspx
Типы указателей (Руководство по программированию на C#) https://msdn.microsoft.com/ru-ru/library/y31yhkeb.aspx
Оператор fixed (Справочник по C#) https://msdn.microsoft.com/ru-ru/library/f58wzh21.aspx
Ключевое слово stackalloc https://msdn.microsoft.com/ru-ru/library/cx9s2sy4.aspx