2017-12-12 9 views
-1

Ich habe Interaktionen zwischen malloc() und verschiedenen String-Funktionen getestet, um zu versuchen, mehr darüber zu lernen, wie Zeiger und Speicher in C arbeiten, aber ich bin etwas verwirrt über die folgenden Interaktionen.malloc und strcpy Interaktionen

char *myString = malloc(5); // enough space for 5 characters (no '\0') 
strcpy(myString, "Hello"); // shouldn't work since there isn't enough heap memory 
printf(%s, %zd\n", myString, strlen(myString)); // also shouldn't work without '\0' 
free(myString); 

Alles oben scheint ordnungsgemäß zu funktionieren. Ich habe versucht, printf() für jedes Zeichen zu verwenden, um zu sehen, ob der Null-Terminator vorhanden ist, aber '\ 0' scheint nur als Leerzeichen zu drucken.

Meine Verwirrung liegt in:

  • Stringliterale immer einen impliziten Nullabschluss haben.
  • strcpy sollte über dem Nullabschluss auf myString kopieren, aber es gibt nicht genug zugeordnet Heap-Speicher
  • printf/Strlen nicht funktionieren sollte, es sei denn myString einen Terminator hat

Da myString offenbar ein Nullabschluss hat , wo ist es? Wurde es nur an einem zufälligen Speicherort platziert? Ist der obige Code ein Fehler, der auf Sie wartet?

+4

Pufferüberlauf. – jxh

+8

Wiederhole nach mir: "Undefiniertes Verhalten" bedeutet "undefiniert". Es bedeutet nicht "garantiert ausfallen", "wird Warnungen erzeugen" oder irgendetwas anderes vorhersagbares. Nur weil es funktioniert, heißt das nicht, dass nichts falsch ist. –

+5

Sie rufen ein undefiniertes Verhalten auf, indem Sie Ihren Puffer überschreiben. Sie haben nur Glück, dass "jedes oben genannte richtig zu funktionieren scheint". Eigentlich sollte ich _un_lucky sagen, weil Sie hoffen, dass Ihr Programm abstürzt, wenn es solche Probleme gibt, damit Sie sie beheben können. Ansonsten manifestieren sie sich am unpassendsten der Zeit ... – yano

Antwort

3

Addressing Ihre drei Punkte:

  • Stringliterale immer einen impliziten Nullabschluss haben.

Korrekt.

  • strcpy sollte über den Nullabschluss auf myString zu kopieren, aber es gibt nicht genug zugeordnet Heap-Speicher

strcpy hat keine Möglichkeit zu wissen, wie groß die Zielpuffer sind, und schreibt gerne über die Ende davon (überschreiben, was auch immer nach dem Puffer im Speicher ist. Für Informationen zu diesem off-the-end-Zugriff nachschlagen 'Pufferüberlauf' oder 'Pufferüberlauf'. Dies sind häufige Sicherheitsschwachstellen). Verwenden Sie für eine sicherere Version strncpy, die die Länge des Zielpuffers als ein Argument nimmt, um nicht über das Ende davon zu schreiben.

  • printf/Strlen nicht funktionieren sollte, es sei denn myString einen Terminator

Die prhase hat 'nicht funktionieren sollte' ist hier ein wenig vage. printf/strlen/etc liest weiter durch den Speicher, bis ein Nullterminator gefunden wird, der unmittelbar hinter der Zeichenkette sein könnte oder Tausende von Bytes entfernt sein könnte (in Ihrem Fall haben Sie den Nullterminator direkt nach myString in den Speicher geschrieben. strlen/etc wird dort aufhören).

Zuletzt: - Ist der obige Code ein Fehler, der auf Sie wartet?

Ja. Sie überschreiben Speicher, der nicht zugewiesen wurde, was je nach dem, was passiert ist, zu Problemen führen kann. Vom strcpy Manpage:

Wenn die Zielzeichenfolge eines strcpy() nicht groß genug ist, dann könnte alles passieren. Das Überfahren von String-Puffern fester Länge ist eine beliebte Cracker-Technik, um die Maschine vollständig zu steuern. Jedes Mal, wenn ein Programm Daten in einen Puffer liest oder kopiert, muss das Programm zuerst prüfen, ob genügend Speicherplatz vorhanden ist. Dies kann unnötig sein, wenn Sie zeigen können, dass ein Überlauf unmöglich ist, aber seien Sie vorsichtig: Programme können sich im Laufe der Zeit ändern, auf eine Weise, die das Unmögliche möglich macht.

+0

Beachten Sie, dass 'strncpy()' nicht über das angegebene Limit hinaus schreibt, der Nachteil ist, dass die kopierten Daten nicht unbedingt eine Zeichenfolge sind; Es könnte am Ende kein Null-Byte haben. –