Kolumne: C# im Fokus

Unsicherer Code via unsafe Zeiger in C – Teil 2
Kommentare

In der letzten Ausgabe der C#-Kolumne wurde bereits das Schlüsselwort unsafe von seiner funktionalen Seite her erläutert. In der heutigen Ausgabe geht es konkret um den Einsatz von Zeigern unter Verwendung von unsafe.

Innerhalb eines als unsafe deklarierten Bereichs sind Zeigeroperationen wie unter C/C++ möglich. Wie in der letzten Ausgabe der Kolumne bereits erläutert wurde, hat die Common Language Runtime (CLR) nur eine eingeschränkte Kontrolle über einen als unsafe deklarierten Ausführungsbereich. Die Syntax und die Funktion von unsafe wurden in der vorherigen C#- Kolumne ausführlich beschrieben. In dieser Ausgabe werden gängige Zeigeroperationen erläutert. Ebenfalls wird demonstriert, wie mittels unsafe eine nicht verwaltete Funktion aus der kernel32-Bibliothek aufgerufen werden kann.

Zeigeroperationen und Referenztypen

Innerhalb eines unsafe-Bereichs sind Zeigerarithmetiken – wie auch unter C bzw. C++ – möglich, d. h., dass Zeiger addiert und subtrahiert werden können. Das ermöglicht einen sehr flexiblen Zugriff auf verschiedene Speicherbereiche. Hierbei muss nur beachtet werden, die Zeiger nicht über Speichergrenzen hinaus zu bewegen. Ansonsten kann es zu unerklärlichem Fehlverhalten bis hin zum Absturz des Programms führen. Listing 1 zeigt ein Beispiel für solche Zeigeroperationen.

Listing 1

public static void PointerOperation()
{
  byte[] field = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  unsafe
  {
    fixed (byte* item = field)
    {
      for (int i = 0; i < field.Length; i++)
        Console.WriteLine(*(item + i));
      for (int i = field.Length - 1; i >= 0; i--)
        Console.WriteLine(*(item + i));
    }
  }

}  

Zunächst wird ein byte-Array mit insgesamt zehn Zahlen initialisiert. Danach wird ein unsafe-Block geöffnet, um Zeigeroperationen zu ermöglichen. Da es sich bei dem Array um einen Referenztypen handelt – es also einen verwalteten Typen darstellt -, kann nicht ohne fixed-Anweisung auf das Array zugegriffen werden. Die fixed-Anweisung sorgt dafür, die Speicheradressen konstant zu halten. Ohne fixed-Anweisung könnte es passieren, dass durch den Garbage-Collection-Prozess Speicheradressen verschoben werden. Somit könnten vorher gültige Speicheradressen plötzlich ungültig werden. Die fixed-Anweisung befestigt die Speicheradressen und unterbindet die Verschiebung von Speicheradressen zur Laufzeit. Da aber die Garbage Collection nicht auf Speicherstrukturen zugreifen kann, die als fixed markiert wurden, sollte das Schlüsselwort vorsichtig und kontrolliert verwendet werden. Nachdem mittels fixed die Speicheradresse fixiert wurde, wird innerhalb einer for-Schleife durch das Zahlenfeld iteriert. Der Zugriff auf die nächsten Elemente erfolgt hierbei aber nicht über den Index, sondern es wird mittels Zeigeraddition jeweils zum nächsten Element gesprungen. Die zweite for-Schleife im Beispiel gibt das Zahlenfeld umgekehrt aus.

Dynamischer Speicher

Die Verwendung des fixed-Schlüsselworts sollte wenn möglich vermieden werden, da ansonsten die Garbage Collection nicht ungehindert arbeiten kann. Teilweise können Implementierungen umgeschrieben werden, damit die fixed-Anweisung nicht zum Einsatz kommen muss. Im Fall eines Arrays kann z. B. durch eigene Speicherallokation auf die explizite Speicherfixierung verzichtet werden. In Listing 2 wird zunächst mittels stackalloc ein int-Array der Größe 10 allokiert. Danach werden die einzelnen Felder des Arrays mit fortlaufenden Werten vorbelegt. Im Anschluss daran werden, wie im Beispiel aus Listing 1, die einzelnen Array-Felder mittels Zeigerzugriff ausgelesen. In diesem Fall kann auf die fixed-Anweisung verzichtet werden, da Speicherbereiche, die über stackalloc allokiert wurden, bereits fixiert sind.

Listing 2

public static void PointerOperation2()
{
  unsafe
  {
    int* dynamicField = stackalloc int[10]; 
    for (int i = 0; i < 10; i++)
      dynamicField[i] = i;
    int* item = &dynamicField[0];
      for (byte i = 0; i < 10; i++)
        Console.WriteLine(*(item + i));
  }      
}  
Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -