C-string-Funktion (strcopy,strcat...,strstr) mit arrays und Zeiger
Immer wenn ich mich mit einer dieser Funktionen in dev-C++(ich weiß, das ist alt, aber aus irgendeinem Grund immer noch gelehrt, an meiner Hochschule.)
strcat,strcpy,strcmp,strchr...//And their variants stricmp...
Das erste argument dieser Funktionen ist immer ein array (ich.e:
char ch[]="hello";
Aber es kann nicht sein, einen Zeiger auf eine Zeichenfolge bc aus irgendeinem Grund dies verursacht einen Absturz.
In der Tat ein Beispiel für eine Blick auf diese beiden codes:
code1:
#include<stdio.h>
#include<string.h>
main()
{char ch[20]="Hello world!";
char *ch2="Hello Galaxy!";
strcat(ch,ch2);
printf("%s",ch);
scanf("%d")//Just to see the output.
}
Dieser code funktioniert einwandfrei und gibt das erwartete Ergebnis(Hallo Welt!Hallo Galaxy!)
Aber die inverse code2 abstürzt.
code2:
#include<stdio.h>
#include<string.h>
main()
{char ch[20]="Hello world!";
char *ch2="Hello Galaxy!";
strcat(ch2,ch);
printf("%s",ch2);
scanf("%d")//Just to see the output.
}
Dieser code stürzt ab und verursacht eine
file.exe has stopped working Error.
Dies ist die gleiche für fast alle Saiten-Funktionen, die zwei Argumente nimmt.
Was ist die Ursache für dieses problem.
- Das ist nicht C++.
main
erfordert eine explizite return-Typ es ist, und der code ist alle C-sonst. - c-faq.com/strangeprob/strlitnomod.html
- ist es nicht ein Pufferüberlauf mit
ch[20]
, sollte es nichtch[25]
? - 26, wenn ich richtig gezählt habe.
- Ja, es ist wahr es gibt überlauf! Aber das ist nicht, wo das problem herkommt,in meinem eigentlichen code 20 200!Tut mir Leid, dass.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Mit
char *ch2 = "Hello Galaxy!";
Sie erhalten einen Zeiger auf ein string-literal. Man sollte nie versuchen zu ändern ein string-Literale, wie dies ruft ein Undefiniertes Verhalten (was in Ihrem Fall hat sich als ein Absturz).Mit
char ch[20] = "Hello World!";
Sie initialisieren ein array mit dem Inhalt einer string-literal, so dass Sie am Ende mit Ihrem eigenen veränderbare Kopie des Strings inch
.Beachten Sie auch, dass 20 Zeichen nicht genug für
Hello World!Hello Galaxy!
zu passen, und auch das ist undefined behaviour, auch bekannt als überlaufende Puffer.ch
ist ein array vonchar
initialisiert die Elemente eines string-literal (und der rest des Arrays initialisiert0
).ch2
ist ein Zeiger auf ein string-literal.String-Literale sind nicht erforderlich, um geändert werden in C. Geändert wird, ein string-literal ist ein nicht festgelegtes Verhalten in C.
Gibt es zwei Probleme. Die erste ist, dass dein string-literal ist nicht lang genug sind, um die verkettete Zeichenfolge
"Hello world!Hello Galaxy!"
. Der Speicherplatz ist nur 13 Byte (12 Zeichen plus den Platz für die '0' - byte beendet, den string). Die verkettete Zeichenfolge benötigt 26 bytes (25 chars + 1 null-Wert char).Dies ist jedoch nicht das eigentliche problem. Das eigentliche problem ist, dass Sie den Zugriff auf den Speicher, dass sollte man nicht sein, und das Betriebssystem oft schützt. Die meisten Implementierungen von C mit vier Bereichen Lagerung:
const
zugeordnet werden.Den ersten drei Bereichen sind im Prinzip änderbar. Der vierte Bereich ist nicht, und wird oft im Speicher abgelegt, dass das Betriebssystem markiert als "read-only". Beim zuweisen der string-literal
"Hello Galaxy!" to
char* ch2, the variable
ch2-Punkte` in den globalen Konstanten-Speicher.Geben Sie eine bessere Idee, den folgenden code Generäle einen segmentation Fault, wenn ich es:
Der segfault Auftritt in der
s[0] = ...
Linie, weil ich den Zugriff auf Speicher, der vom Betriebssystem als schreibgeschützt markiert.Die in etwa der Größe des Zeiger-Arrays..overflow-problem..
char *ch2="Hello Galaxy!";
wenn Sie diese automatisch die Größe von *ch2 bekommt 14 mit dem null-Zeichen, aber wenn Sie sich bewegen, diech[]
array in die*ch2
, erhalten Sie eine Fehlermeldung. Sie kann sich nicht bewegen ein array mit 20 Größe in ein anderes array mit Größe 14...String-Literale sind schreibgeschützt.Dies bedeutet, dass, wenn Sie zuweisen:
Können Sie T-pass-str als erstes argument von strcpy und strcat, denn dies würde dazu führen, schreiben Sie über nur-lese-Speicher.
Wenn Sie stattdessen erklären es so:
Dann die str2-array auf dem stack gespeichert werden, und Sie können ändern Sie die Werte.
Sie können immer noch pass-str-Funktionen wie strcmp (die gerade liest, die wto-strings und vergleichen Sie Sie), oder als zweites argument von strcat und strcpy, da diese nicht dazu führen, dass der string geschrieben werden.
du hast einen Fehler, weil Sie versuchen, Zugriff auf den code-Abschnitt des Prozesses, die schreibgeschützt ist.
das ist dein string-literal vorhanden im code und die Adresse des string-literal verwenden Sie in Zuordnung zu den Zeiger-variable.
So können Sie Zugriff auf den code, aber Sie können nicht ändern, diese.
jeder ausführbaren Datei enthalten einige Abschnitte, die
wie...
1.text(code des Programms als auch als string-Literale ist hier vorhanden)
2.Daten nicht initialisierte
3.Daten initialisiert
können Sie veryfy dies durch den Befehl
Auch mit dem Befehl