Segmentierungsfehler mit Char Array und Zeiger in C unter Linux
Lesezeit: 2 Minuten
Also ich habe folgendes Programm:
int main(){
char* one = "computer";
char two[] = "another";
two[1]='b';
one[1]='b';
return 0;
}
Es segfaults auf der Zeile “one .”[1]=’b'”, was sinnvoll ist, da der Speicher, auf den der Zeiger “one” zeigt, im Nur-Lese-Speicher sein muss. Die Frage ist jedoch, warum die Zeile “two[1]=’b'” segfault? Betrachten Sie die Assembly-Ausgabe von gcc:
Wir sehen, dass sich beide Strings im Rodata-Abschnitt befinden und somit schreibgeschützt sind. Wie kommt es dann zu der Zeile “zwei[1]=’b’ führt keinen Segfault aus?
Siehe auch die andere, aber verwandte Frage stackoverflow.com/questions/177062/…
– Pascal Cuoq
20. November ’09 um 20:43
mmx
one zeigt direkt auf die Zeichenfolge, die sich auf einer schreibgeschützten Seite befindet. Auf der anderen Seite, two ist ein Array, das auf dem Stack zugewiesen ist und mit einigen konstanten Daten initialisiert wird. Zur Laufzeit wird die Zeichenfolge im schreibgeschützten Abschnitt der ausführbaren Datei auf den Stack kopiert. Was Sie ändern, ist die Kopie dieser Zeichenfolge auf dem Stack, nicht die schreibgeschützte Speicherseite.
Auf einer höheren Ebene, aus sprachlicher Sicht, "abcd" ist ein Ausdruck von Typ const char* und nicht char*. Daher führt das Ändern des Werts, auf den ein solcher Ausdruck zeigt, zu undefiniertem Verhalten. Die Aussage char* one = "something"; speichert lediglich den Zeiger auf den String in einer Variablen (unsicher, da er weggeworfen wird) const Modifikator). Der char two[] = "something"; ist ganz anders. Es deklariert tatsächlich ein Array und initialisiert es, ähnlich wie int a[] = {1,2,3};. Die Zeichenfolge in Anführungszeichen ist hier der Initialisierungsausdruck.
Wow… ich programmiere jetzt seit ca. 5 Jahren in C und war mir dessen nicht bewusst char[] eine Kopie der konstanten Daten erstellt. Ich dachte immer [] war nur eine schickere Art zu schreiben *. Danke schön! +1
– Earlz
20. November ’09 um 20:39 Uhr
ich schreibe oft char str[] = {"Something"}; um die Assoziation zu verdeutlichen.
– LnxPrgr3
20. Nov. 09 um 21:01
Remo.D
Das “andere”, das Sie im Rodata-Abschnitt sehen, wird in das Array kopiert two wann es initialisiert wird. Auf der anderen Seite die die Anschrift der Zeichenfolge “Computer” wird einem zugewiesen.
So, one zeigt auf ein Nur-Lese-Segment (und damit auf den Segfault beim Schreiben) während two wird auf dem Stack zugewiesen und dann wird “ein anderer” hineinkopiert.
Die zweite Form erstellt ein Array durch Kopieren der Literalzeichenfolge.
Siehe auch die andere, aber verwandte Frage stackoverflow.com/questions/177062/…
– Pascal Cuoq
20. November ’09 um 20:43