Warum löst strcpy einen Segmentierungsfehler mit globalen Variablen aus?

7

Ich habe also einen C-Code:

%Vor%

Dies kompiliert, läuft und verhält sich so, wie es aussieht. Wenn jedoch einer oder beide Zeichenzeiger als globale Variable deklariert sind, führt strcpy zu einem Segmentierungsfehler. Warum passiert das? Offensichtlich gibt es einen Fehler in meinem Verständnis von Umfang.

    
codemonkey 23.09.2008, 18:35
quelle

8 Antworten

16

Wie andere Poster erwähnt haben, liegt die Ursache des Problems darin, dass temp nicht initialisiert ist. Wenn es auf dem Stapel als automatische Variable deklariert wird, enthält es den Müll, der sich an diesem Speicherort befindet. Anscheinend ist für den Compiler + CPU + OS, den Sie ausführen, der Müll an dieser Stelle ein gültiger Zeiger. Der strcpy "ist erfolgreich", da er nicht segfault ist, aber tatsächlich hat er einen String an eine beliebige Stelle irgendwo im Speicher kopiert. Diese Art von Speicherkorruptionsproblemen bringt überall Angst in die Herzen von C-Programmierern, da es außerordentlich schwierig zu debuggen ist.

Wenn Sie die temp-Variablendeklaration in den globalen Bereich verschieben, wird sie in den BSS-Abschnitt eingefügt und automatisch auf Null gesetzt. Versuche, * temperature zu dereferenzieren, führen dann zu einem segfault.

Wenn Sie * den Pfad zum globalen Bereich verschieben, bewegt sich * temp um eine Position auf dem Stapel nach oben. Der Müll an diesem Ort ist anscheinend kein gültiger Zeiger und daher führt Dereferenzierung * temp zu einem segfault.

    
DGentry 23.09.2008, 18:43
quelle
9

Die temporäre Variable zeigt nicht auf Speicher (Speicher) und ist nicht initialisiert.

Wenn temp als char temp[32]; deklariert wird, dann würde der Code funktionieren, egal wo er deklariert ist. Es gibt jedoch andere Probleme mit der Deklaration von Temp mit einer festen Größe wie dieser, aber das ist eine Frage für einen anderen Tag.

Nun, warum stürzt es ab, wenn es global und nicht lokal deklariert wird. Glück ...

Wenn es lokal deklariert wird, kommt der Wert von temp von dem Wert, der sich zu diesem Zeitpunkt auf dem Stack befinden könnte. Es ist Glück, dass es auf eine Adresse zeigt, die keinen Absturz verursacht. Es wird jedoch Speicher gelöscht, der von jemand anderem verwendet wird.

Wenn global deklariert, werden diese Variablen in den meisten Prozessoren in Datensegmenten gespeichert, die Seiten mit Bedarf null verwenden. Daher erscheint char *temp so, als wäre char *temp=0 deklariert worden.

    
Torlack 23.09.2008 18:39
quelle
8

Sie haben vergessen, temp zuzuweisen und zu initialisieren:

%Vor%

Stellen Sie nur sicher, dass TEMP_SIZE groß genug ist. Sie können dies auch zur Laufzeit berechnen und dann sicherstellen, dass die Größe ausreicht (sollte mindestens strlen (Pfad) sein)

    
terminus 23.09.2008 18:36
quelle
3

Wie oben erwähnt, haben Sie vergessen, Speicherplatz für temp. Ich bevorzuge strdup bis malloc+strcpy . Es macht was du willst.

    
Sridhar Iyer 23.09.2008 18:43
quelle
2

Nein - das funktioniert nicht unabhängig von den Variablen - es sieht einfach so aus, als hättest du (un) Glück gehabt. Sie müssen Speicherplatz reservieren, um den Inhalt der Zeichenfolge zu speichern, anstatt die Variable nicht initialisiert zu lassen.

Nichtinitialisierte Variablen auf dem Stapel zeigen auf ziemlich zufällige Speicherorte. Wenn diese Adressen gültig sind, trampelt dein Code überall herum, aber es wird kein Fehler angezeigt (aber es kann zu Fehlern in der Speicherbeschädigung kommen, die anderswo in deinem Code auftreten).

Globale Fehler schlagen regelmäßig fehl, da sie normalerweise auf bestimmte Muster festgelegt werden, die auf nicht zugeordneten Speicher verweisen. Wenn Sie versuchen, diese zu dereferenzieren, erhalten Sie sofort einen segfault (was besser ist - wenn Sie es später lassen, wird es sehr schwer, den Fehler zu finden).

    
Brian 23.09.2008 18:43
quelle
2

Ich würde gerne das erste Adam-Fragment als

umschreiben %Vor%

So wie Sie:

%Vor%

Der zweite Punkt ist der Verlust des letzten Zeichens Ihrer Quellzeichenfolge, wenn es & gt; = 256 Zeichen lang ist.

    
Rob Wells 23.09.2008 18:57
quelle
1

Der wichtige zu beachtende Teil:
Zielzeichenfolge dest muss groß genug sein, um die Kopie zu erhalten.
In Ihrer Situation hat temp keinen Speicher zum Kopieren in.

Von der man-Seite von strcpy kopiert:

%Vor%     
Martin York 23.09.2008 18:39
quelle
1

Sie rufen ein undefiniertes Verhalten auf, da Sie die Variable temp nicht initialisieren. Es zeigt auf einen zufälligen Speicherort im Speicher, so dass Ihr Programm funktioniert , aber höchstwahrscheinlich wird es segfault. Die Zielzeichenfolge muss ein Array sein oder auf dynamischen Speicher verweisen:

%Vor%

Verwenden Sie außerdem strncpy() anstelle von strcpy() , um Pufferüberläufe zu vermeiden.

    
Adam Rosenfield 23.09.2008 18:39
quelle