ProgrammierungBackend C Entwickler

Wie implementiert man sicheres Kopieren von Speicher zwischen Arrays in C? Welche Funktionen der Standardbibliothek sollte man verwenden und was ist der Unterschied zwischen ihnen?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort

Geschichte der Frage

Sicheres Kopieren von Speicher ist eine der häufigsten und kritischsten Aufgaben in C. Ursprünglich verwendeten Programme eine Schleife für das byteweise Kopieren. Später wurden Standardfunktionen wie memcpy, memmove sowie sicherere Alternativen wie strncpy für Strings hinzugefügt. Falsches Kopieren führt zu Pufferüberläufen und Sicherheitsanfälligkeiten.

Problem

Die Verwendung einer ungeeigneten Funktion oder einer falschen Größe beim Kopieren kann Daten beschädigen oder sogar einen Weg für sicherheitsinteressierte Dritte öffnen. Es ist entscheidend, die Fälle zu unterscheiden, in denen memmove verwendet wird und wann memcpy zulässig ist, um Fehler mit überlappenden Speicherbereichen zu vermeiden.

Lösung

Für sicheres Kopieren von nicht-String Speicher verwenden Sie:

memcpy(dest, src, n);
  • memcpy kopiert schnell n Bytes von src nach dest, wenn ihre Speicherbereiche sich nicht überlappen.
  • Wenn sich die Bereiche überlappen können, verwenden Sie memmove:
memmove(dest, src, n);

Für das Kopieren von Strings verwenden Sie entweder strncpy oder besser, moderne und sichere Alternativen, wenn verfügbar (strlcpy).

Hauptmerkmale:

  • memcpy ist nur sicher, wenn keine Überlappung von src und dest vorliegt.
  • memmove funktioniert korrekt, selbst mit überlappenden Speicherbereichen.
  • Für Strings sollten spezielle Funktionen verwendet werden, die den nullterminierenden Charakter berücksichtigen.

Trickfragen.

1. Was ist der Unterschied zwischen memcpy und memmove und wann ist welche Funktion notwendig?

memcpy ist sehr schnell, aber nicht für überlappende Speicherbereiche gedacht — das Ergebnis wird unvorhersehbar sein. memmove garantiert korrektes Kopieren, unabhängig von der Überlappung:

int arr[] = {1,2,3,4,5}; // memmove: Sicheres Kopieren bei Überlappung memmove(arr+1, arr, 4 * sizeof(int));

2. Ist es sicher, strcpy zum Kopieren eines Strings in einen kleineren Puffer zu verwenden?

Nein, die Funktion strcpy überprüft die Größe des Zielpuffers nicht. Dies führt häufig zu Pufferüberläufen. Es ist besser, strncpy oder strlcpy (wenn verfügbar) zu verwenden oder die Größe explizit zu kontrollieren:

char dest[5]; strncpy(dest, src, sizeof(dest)-1); // src muss kürzer als 5 Zeichen sein

3. Kann memcpy zum Kopieren von Strukturen mit Zeigern verwendet werden?

Ja, aber dabei werden nur die Zeiger selbst kopiert, nicht die Daten an diesen Adressen. Dies kann zu Problemen bei der Arbeit mit dem Speicher und doppelten Freigaben führen.

Typische Fehler und Anti-Pattern

  • Verwendung von memcpy bei überlappenden Speicherbereichen.
  • Ignorieren der Größe des Zielpuffers.
  • Kopieren von Strukturen mit Zeigern mit einfachem memcpy (shallow copy).

Beispiel aus dem Leben

Negativer Fall

Ein langer String wird mit strcpy in einen kleinen Puffer kopiert, ohne die Länge der Quelle zu überprüfen. Es kommt zu einem Pufferüberlauf, was zu einer Sicherheitsanfälligkeit führt.

Vorteile:

  • Minimale Codierung, schnelle Ausführung.

Nachteile:

  • Sicherheitsanfälligkeit, mögliche Abstürze, Speicherbeschädigung.

Positiver Fall

Verwendung von strncpy oder memmove mit genauer Größenkontrolle, manuell wird das abschließende Nullzeichen des Strings sichergestellt.

Vorteile:

  • Vorhersehbares Verhalten, Schutz vor Pufferüberläufen.

Nachteile:

  • Erfordert zusätzliche Längenprüfung und möglicherweise eine geringe Geschwindigkeitsminderung aufgrund zusätzlicher Prüfungen.