C# Language
Niebezpieczny kod w .NET
Szukaj…
Uwagi
- Aby móc użyć
unsafe
słowa kluczowego w projekcie .Net, musisz zaznaczyć „Zezwalaj na niebezpieczny kod” we właściwościach projektu => kompilacja - Korzystanie z niebezpiecznego kodu może poprawić wydajność, jednak odbywa się to kosztem bezpieczeństwa kodu (stąd określenie
unsafe
).
Na przykład, gdy używasz pętli for, tablica taka:
for (int i = 0; i < array.Length; i++)
{
array[i] = 0;
}
.NET Framework zapewnia, że nie przekroczysz granic tablicy, IndexOutOfRangeException
jeśli indeks przekroczy granice.
Jeśli jednak użyjesz niebezpiecznego kodu, możesz przekroczyć granice tablicy w następujący sposób:
unsafe
{
fixed (int* ptr = array)
{
for (int i = 0; i <= array.Length; i++)
{
*(ptr+i) = 0;
}
}
}
Indeks niebezpiecznych tablic
void Main()
{
unsafe
{
int[] a = {1, 2, 3};
fixed(int* b = a)
{
Console.WriteLine(b[4]);
}
}
}
Uruchomienie tego kodu tworzy tablicę o długości 3, ale następnie próbuje uzyskać 5. pozycję (indeks 4). Na mojej maszynie wydrukowano 1910457872
, ale zachowanie nie jest zdefiniowane.
Bez unsafe
bloku nie można używać wskaźników, a zatem nie można uzyskać dostępu do wartości poza końcem tablicy bez powodowania zgłoszenia wyjątku.
Używanie niebezpiecznych z tablicami
Podczas uzyskiwania dostępu do tablic za pomocą wskaźników nie ma sprawdzania granic, a zatem nie będzie IndexOutOfRangeException
żaden IndexOutOfRangeException
. Dzięki temu kod jest szybszy.
Przypisywanie wartości do tablicy za pomocą wskaźnika:
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
}
}
}
}
}
Natomiast bezpiecznym i normalnym odpowiednikiem byłoby:
class Program
{
static void Main(string[] args)
{
int[] array = new int[1000];
for (int i = 0; i < array.Length; i++)
{
array[i] = i;
}
}
}
Niebezpieczna część będzie na ogół szybsza, a różnica w wydajności może się różnić w zależności od złożoności elementów w tablicy, jak również zastosowanej logiki. Chociaż może być szybszy, należy go używać ostrożnie, ponieważ jest trudniejszy w utrzymaniu i łatwiejszy do złamania.
Używanie niebezpiecznych z łańcuchami
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"