C# Language
Небезопасный код в .NET.
Поиск…
замечания
- Чтобы использовать ключевое слово
unsafe
в проекте .Net, вы должны установить флажок «Разрешить небезопасный код» в Project Properties => Build - Использование небезопасного кода может повысить производительность, однако это за счет безопасности кода (отсюда и термин
unsafe
).
Например, когда вы используете цикл for для такого массива:
for (int i = 0; i < array.Length; i++)
{
array[i] = 0;
}
.NET Framework гарантирует, что вы не превысите границы массива, бросая IndexOutOfRangeException
если индекс превышает границы.
Однако, если вы используете небезопасный код, вы можете превысить границы массива следующим образом:
unsafe
{
fixed (int* ptr = array)
{
for (int i = 0; i <= array.Length; i++)
{
*(ptr+i) = 0;
}
}
}
Небезопасный индекс массива
void Main()
{
unsafe
{
int[] a = {1, 2, 3};
fixed(int* b = a)
{
Console.WriteLine(b[4]);
}
}
}
Запуск этого кода создает массив длиной 3, но затем пытается получить 5-й элемент (индекс 4). На моей машине это напечатано 1910457872
, но поведение не определено.
Без unsafe
блока вы не можете использовать указатели и, следовательно, не можете получать доступ к значениям за конец массива, не вызывая исключения.
Использование небезопасных массивов
При доступе к массивам с помощью указателей проверка границ не выполняется, поэтому исключение IndexOutOfRangeException
не будет выбрано. Это делает код быстрее.
Присвоение значений массиву с указателем:
class Program
{
static void Main(string[] args)
{
unsafe
{
int[] array = new int[1000];
fixed (int* ptr = array)
{
for (int i = 0; i < array.Length; i++)
{
*(ptr+i) = i; //assigning the value with the pointer
}
}
}
}
}
В то время как безопасный и нормальный аналог будет:
class Program
{
static void Main(string[] args)
{
int[] array = new int[1000];
for (int i = 0; i < array.Length; i++)
{
array[i] = i;
}
}
}
Небезопасная часть, как правило, будет быстрее, и разница в производительности может варьироваться в зависимости от сложности элементов в массиве, а также от логики, применяемой к каждому из них. Несмотря на то, что это может быть быстрее, его следует использовать с осторожностью, поскольку его сложнее поддерживать и легче сломать.
Использование небезопасных строк
var s = "Hello"; // The string referenced by variable 's' is normally immutable, but
// since it is memory, we could change it if we can access it in an
// unsafe way.
unsafe // allows writing to memory; methods on System.String don't allow this
{
fixed (char* c = s) // get pointer to string originally stored in read only memory
for (int i = 0; i < s.Length; i++)
c[i] = 'a'; // change data in memory allocated for original string "Hello"
}
Console.WriteLine(s); // The variable 's' still refers to the same System.String
// value in memory, but the contents at that location were
// changed by the unsafe write above.
// Displays: "aaaaa"