strncpy führt zu Segmentierungsfehler

8

Ich mache nur mit strncpy rum.

Mein Programm sieht so aus

%Vor%

Hier, bevor ich Strncpy habe ich ein "\ 0" Zeichen in "src" Zeichenfolge hinzugefügt, Länge von "src" Zeichenfolge wird 3, Ziel-Array ist der Größe 10. Aber in Strncpy habe ich die Anzahl der Bytes zu sein kopiert als 100.

Das bedeutet, dass meine Quellzeichenfolge NULL beendet ist. Jetzt sollte strncpy wie jede String-Funktion versuchen, nur 3 Byte zu kopieren, selbst wenn die Anzahl der von mir bereitgestellten Bytes mehr als 3 (in diesem Fall 100) beträgt. Es tut das, aber ich bekomme auch einen Segmentierungsfehler.

Mein Ergebnis ist unten gezeigt.

%Vor%

Warum passiert dieser Segmentierungsfehler hier?

Kann mir jemand hier helfen?

    
Himanshu Gupta 28.12.2012, 06:12
quelle

4 Antworten

13

Ich könnte Sie auf Man-Pages, Websites usw. hinweisen, aber letztendlich zählt der C-Standard selbst. Als Teil der Standard-Laufzeitbibliothek sind die Verwendung und das Verhalten in C99-§7.23.2.4 definiert als:

%Vor%
  

Beschreibung   Die Funktion strncpy kopiert nicht mehr als n Zeichen (Zeichen, die einem Nullzeichen folgen, werden nicht kopiert) von dem Array, auf das s2 zeigt, auf das Array, auf das gezeigt wird   s1. Wenn zwischen überlappenden Objekten kopiert wird, ist das Verhalten nicht definiert.   Wenn das Array, auf das s2 zeigt, eine Zeichenfolge ist, die kürzer als n Zeichen ist, werden Nullzeichen an die Kopie in dem Array angehängt, auf das s1 zeigt, bis alle n Zeichen geschrieben sind.

     

Gibt zurück   Die Funktion strncpy gibt den Wert von s1 zurück.

Es gibt signifikante implizierte Informationen hier, wobei die wichtigste Bedeutung ist: strncpy() wird NICHT die Zielzeichenfolge mit einem Nullzeichen beenden, wenn die Länge der Quellzeichenfolge (einschließlich sein Null-Zeichen-Terminator erfüllt oder überschreitet die spezifizierte Zielpufferlänge).

Darüber hinaus verwirrt es mich weiterhin, obwohl es im Standard (siehe oben) klar spezifiziert ist, wie viele Ingenieure NICHT wissen, dass strncpy() den Ziel-String-Puffer mit Null-Zeichen füllt, bis der Die angegebene Länge n ist erreicht, wenn die Länge der Quellzeichenfolge kleiner als die Zielpuffergröße ist. Daraus ergibt sich folgende unausweichliche Schlussfolgerung:

Die strncpy() API schreibt IMMER n Zeichen in die Adresse, auf die der Zielpuffer verweist.

Da in Ihrem Fall der Zielpuffer nur 10 Zeichen breit ist, schreiben Sie 90 zusätzliche Zeichen über das definierte Ende des Schreibspeichers hinaus und gehen so in das Land .

An diesem Punkt müssen Sie sich fragen: "Also, was ist der Gebrauch?" Dort ist ein wohl fundamentaler Anwendungsfall. Es erlaubt Ihnen, bis zu n chars in den Zielpuffer zu kopieren, mit der Voraussagbarkeit, dass Sie nicht über n chars überschreiten. Zeitraum. Letztendlich möchten Sie jedoch eine Null-terminierte Zeichenfolge, also die richtige Verwendung ist dies:

%Vor%

Dabei ist N die harte Länge des dst -Puffers in Zeichen und ist größer als oder gleich 1 . Beachten Sie, dass dst genau so gut ein dynamisch zugewiesener Speicherzeiger sein könnte:

%Vor%

Mit dem oben Gesagten haben Sie immer eine Null-terminierte Zeichenkette bei dst . Wenn die Quellzeichenfolge length kleiner als die angegebene Zielpufferlänge ist, füllt strncpy() den Rest des Puffers mit Nullzeichen, bis eine Gesamtzahl von Quellzeichen - kopiert + mit Schwanz gefüllt - ist. Nullzeichen entsprechen n und die abschließende Anweisung ist redundant. Wenn die Länge der Quellzeichenfolge gleich oder größer als die Zielpufferlänge ist, beendet strncpy() den Kopiervorgang, sobald N-1 chars erreicht ist, und die finale Anweisung setzt ein Nullzeichen am Ende der Zeichenfolge Puffer. Dies führt zu einer "cut-down" Präfix-Zeichenfolge der ursprünglichen Quelle, aber am wichtigsten ist, dass es sicherstellt, dass Sie die Grenzen des Zielpuffers NICHT überschreiten mit einem späteren String-API-Aufruf, der nach einem Terminator sucht.

Die Nützlichkeit der obigen Technik ist immer umstritten. Ich bin ein C ++ - Typ, also rettet std::string mein Happy-Self vor all dem Wahnsinn. Aber die Realität ist folgendes: Manchmal ist es Ihnen egal, ob src nicht in seine Gesamtheit nach dst kopiert wird; manchmal nicht. Der Nutzen ist situationsabhängig stark. Um String-Daten in einer UI darzustellen, spielt dies (wahrscheinlich) keine Rolle. Zum Kopieren einer Zeichenfolge, die für kritische Daten verwendet werden soll, wird eine partielle Präfix-Teilzeichenfolge nicht akzeptiert. Wenn die Polizei einen Haftbefehl gegen "Joseph Johnson Jr." ausstellt, wird es einige Erklärungen geben, wenn sein Vater ("Joseph Johnson") ins Gefängnis kommt, weil der Namenspuffer der Warrant-Issue-Software nur 15 Zeichen enthielt .

Alles in allem hängt Ihr Segmentierungsfehler mit dieser Aussage zusammen:

%Vor%

Rufen Sie die obige fettgedruckte Anweisung erneut auf: " strncpy() schreibt IMMER n -Zeichen an die Adresse, auf die der Zielpuffer verweist." . Dies bedeutet, dass der obige Code immer 100 Zeichen in den Zielpuffer schreibt, was in Ihrem Fall nur 10 Zeichen breit ist, also undefiniertes Verhalten und wahrscheinlich ker-boom .

Korrigieren Sie dies, indem Sie Folgendes tun, wenn der Zielpuffer ein Zeichenfeld fester Länge ist:

%Vor%

Siehe die vorherige Verwendung, wie man dies für dynamische Zeichenketten der Länge 'N chars.

macht     
WhozCraig 28.12.2012, 08:59
quelle
5

Von Ссылка

  

char * strncpy (char * Ziel, const char * Quelle, size_t num   );

     

Zeichen aus Zeichenfolge kopieren Kopiert die ersten Zahlen der Quelle   zum Ziel. Wenn das Ende der Quelle C-Zeichenfolge (die signalisiert wird   durch ein Null-Zeichen) gefunden, bevor num Zeichen kopiert wurden,   Das Ziel wird mit Nullen aufgefüllt, bis eine Gesamtzahl von Zeichen vorhanden ist   wurde darauf geschrieben.

Obwohl die Länge der Quellzeichenfolge kleiner als die Größe der Zielpuffergröße ist, versucht sie dennoch, aufgrund des Weiterleitungsverhaltens von strncpy den Rest der Zeichen über die Zielpuffergröße hinaus zu überlagern, was zu Segmentationsfehler

führt

Anstatt mehr als 100 Zeichen zu kopieren, sollte die Größe der maximal zulässigen Größe im Zielpuffer entsprechen. Sie könnten also

geschrieben haben %Vor%

oder besser, um ein _countof Makro

zu schreiben %Vor%     
Abhijit 28.12.2012 06:16
quelle
1

Siehe: Ссылка

Die Funktionen stpncpy () und strncpy () kopieren höchstens n Zeichen von s2      in s1. Wenn s2 weniger als n Zeichen lang ist, ist der Rest von s1      gefüllt mit '\ 0' Zeichen. Andernfalls wird s1 nicht beendet.

Der Rest ist gefüllt ....

Also:

%Vor%     
Mario The Spoon 28.12.2012 06:15
quelle
0

strncpy(s1.from_str,src,100);

Warum verwenden Sie 100 in Ihrer Funktion, from_str und src haben beide 10 aufeinanderfolgende Bytes zugewiesen, aber Sie kopieren 100 Bytes, was zu seg führt. Fehler.

Verwenden Sie so,

strncpy(s1.from_str,src,10);

    
Adeel Ahmed 28.12.2012 06:20
quelle

Tags und Links