Bearbeiten: Ich habe die Quelle für das Beispiel hinzugefügt.
Ich bin auf dieses Beispiel gestoßen :
char source[MAX] = "123456789";
char source1[MAX] = "123456789";
char destination[MAX] = "abcdefg";
char destination1[MAX] = "abcdefg";
char *return_string;
int index = 5;
/* This is how strcpy works */
printf("destination is originally = '%s'\n", destination);
return_string = strcpy(destination, source);
printf("after strcpy, dest becomes '%s'\n\n", destination);
/* This is how strncpy works */
printf( "destination1 is originally = '%s'\n", destination1 );
return_string = strncpy( destination1, source1, index );
printf( "After strncpy, destination1 becomes '%s'\n", destination1 );
Welches hat diese Ausgabe erzeugt:
Ziel ist ursprünglich = 'abcdefg' Nach strcpy wird das Ziel zu '123456789'. Ziel1 ist ursprünglich = 'abcdefg' Nach strncpy wird destination1 zu '12345fg'.
Was mich wundert, warum jemand diesen Effekt haben möchte. Es sieht so aus, als wäre es verwirrend. Dieses Programm lässt mich denken, dass Sie mit Tom Bro763 grundsätzlich den Namen einer Person (z. B. Tom Brokaw) kopieren könnten.
Was sind die Vorteile der Verwendung strncpy()
gegenüber strcpy()
?
strcpy
stattdessen verwendenstrncpy
?"getline
zu falschen Ergebnissen führen würde, wenn ich sie anhand sorgfältig ausgearbeiteter Eingaben benotete. :)Antworten:
strncpy
Bekämpft den Pufferüberlauf, indem Sie eine Länge eingeben müssen.strcpy
hängt von einem Trailing ab\0
, das möglicherweise nicht immer auftritt.Zweitens ist es mir ein Rätsel, warum Sie nur 5 Zeichen auf 7 Zeichenfolgen kopieren, aber es führt zu erwartetem Verhalten. Es wird nur über die ersten
n
Zeichen kopiert , wobein
das dritte Argument ist.Die
n
Funktionen werden alle als defensive Codierung gegen Pufferüberläufe verwendet. Bitte verwenden Sie sie anstelle älterer Funktionen, wie zstrcpy
.quelle
strncpy
wurde ursprünglich in die C-Bibliothek eingeführt, um Namensfelder mit fester Länge in Strukturen wie Verzeichniseinträgen zu behandeln. Solche Felder werden nicht wie Zeichenfolgen verwendet: Die nachfolgende Null ist für ein Feld mit maximaler Länge nicht erforderlich, und das Setzen von nachgestellten Bytes für kürzere Namen auf Null gewährleistet effiziente feldweise Vergleiche.strncpy
ist nicht ursprünglich ein "begrenzter Strcpy", und der Ausschuss hat es vorgezogen, bestehende Praktiken anzuerkennen, anstatt die Funktion zu ändern, um sie besser für eine solche Verwendung geeignet zu machen.strncpy
ist nicht eine sicherere Versionstrcpy
.strncpy
anstattstrcpy
weil es eine viel defensivere Funktion ist ... was ich gesagt habe.snprintf
, ist aber irrelevantstrncat
und für völlig falschstrncpy
. Wie konnte diese Antwort jemals so viele positive Stimmen bekommen? Es zeigt, wie schlimm die Situation in Bezug auf diese Scheinfunktion ist. Die Verwendung ist nicht defensiv: In den meisten Situationen versteht der Programmierer seine Semantik nicht und erstellt eine möglicherweise nicht nullterminierte Zeichenfolge.Die
strncpy()
Funktion wurde unter Berücksichtigung eines ganz bestimmten Problems entwickelt: Manipulieren von Zeichenfolgen, die in der Art der ursprünglichen UNIX-Verzeichniseinträge gespeichert sind. Diese verwendeten ein Array mit fester Größe, und ein Nullterminator wurde nur verwendet, wenn der Dateiname kürzer als das Array war.Das ist es, was hinter den beiden Kuriositäten steckt
strncpy()
:Für ein "sichereres
strcpy()
" ist es besser, wenn Sie Folgendes verwendenstrncat()
:Dadurch wird das Ergebnis immer nicht beendet und es wird nicht mehr als erforderlich kopiert.
quelle
strncat()
Verkettet die Quellzeichenfolge mit dem Ende der Zielzeichenfolge . Wir wollen nur die Quellzeichenfolge in das Ziel kopieren, also setzen wir das Ziel zuerst auf die leere Zeichenfolge - das ist, wasdest[0] = '\0';
tut.Obwohl ich die Absicht dahinter kenne
strncpy
, ist es keine wirklich gute Funktion. Vermeiden Sie beides. Raymond Chen erklärt .Siehe auch Warum ist strncpy unsicher?
quelle
strncpy ist NICHT sicherer als strcpy, es tauscht nur eine Art von Fehlern mit einer anderen. In C müssen Sie beim Umgang mit C-Strings die Größe Ihrer Puffer kennen, daran führt kein Weg vorbei. strncpy war für das von anderen erwähnte Verzeichnis gerechtfertigt, aber ansonsten sollten Sie es niemals verwenden:
quelle
Was Sie suchen, ist die Funktion,
strlcpy()
die den String immer mit 0 beendet und den Puffer initialisiert. Es ist auch in der Lage, Überläufe zu erkennen. Einziges Problem, es ist nicht (wirklich) portabel und nur auf einigen Systemen (BSD, Solaris) vorhanden. Das Problem mit dieser Funktion ist, dass sie eine weitere Dose Würmer öffnet, wie aus den Diskussionen auf http://en.wikipedia.org/wiki/Strlcpy hervorgehtMeine persönliche Meinung ist, dass es weitaus nützlicher ist als
strncpy()
undstrcpy()
. Es hat eine bessere Leistung und ist ein guter Begleiter zusnprintf()
. Für Plattformen, die es nicht haben, ist es relativ einfach zu implementieren. (Für die Entwicklungsphase einer Anwendung ersetze ich diese beiden Funktionen (snprintf()
undstrlcpy()
) durch eine Überfüllungsversion, die das Programm bei Pufferüberläufen oder -kürzungen brutal abbricht. Dadurch können die schlimmsten Straftäter schnell erkannt werden. Insbesondere, wenn Sie an einer Codebasis von jemand anderem arbeiten .EDIT:
strlcpy()
kann einfach implementiert werden:quelle
dstsize > 0
und nichts tun, wenn dies nicht der Fall ist.dstsize
diememcpy
Längelen
des Zielpuffers ausgelöst und übergelaufen wird.Die
strncpy()
Funktion ist sicherer: Sie müssen die maximale Länge übergeben, die der Zielpuffer akzeptieren kann. Andernfalls kann es vorkommen, dass die Quellzeichenfolge nicht korrekt mit 0 abgeschlossen ist. In diesem Fall wird diestrcpy()
Funktion mehr Zeichen in das Ziel schreiben und alles beschädigen, was sich nach dem Zielpuffer im Speicher befindet. Dies ist das Pufferüberlaufproblem, das bei vielen Exploits verwendet wirdAuch für POSIX-API-Funktionen, bei
read()
denen die abschließende 0 nicht in den Puffer gestellt wird, sondern die Anzahl der gelesenen Bytes zurückgegeben wird, setzen Sie die 0 entweder manuell oder kopieren sie mitstrncpy()
.In Ihrem Beispielcode
index
handelt es sich eigentlich nicht um einen Index, sondern um acount
- es gibt an, wie viele Zeichen höchstens von der Quelle zum Ziel kopiert werden sollen. Wenn unter den ersten n Bytes der Quelle kein Nullbyte vorhanden ist, wird die im Ziel platzierte Zeichenfolge nicht mit Null terminiertquelle
strncpy füllt das Ziel mit '\ 0' für die Größe der Quelle, obwohl die Größe des Ziels kleiner ist ....
Manpage:
quelle
strncpy
füllt das Ziel mit '\ 0' für die Größenargument, wenn die Länge der Quelle geringer ist. Das Größenargument ist nicht die Größe der Quelle, nicht die maximale Anzahl von Zeichen, die aus der Quelle kopiert werden sollen, da es sichstrncat
um die Größe des Ziels handelt.strncpy
gegenüber anderen Kopiervorgängen besteht darin, dass garantiert wird, dass das gesamte Ziel geschrieben wird. Da Compiler möglicherweise versuchen, beim Kopieren von Strukturen, die einige unbestimmte Werte enthalten, "kreativ" zu werden, kann es am einfachsten sein, sicherzustellen, dass alle Zeichenarrays in Strukturen vollständig geschrieben werden, um "Überraschungen" zu vermeiden.strncpy
um eine Null-Beendigung zu gewährleisten:strncpy(dest, src, dest_size)[dest_size - 1] = '\0';
char[8]
innerhalb einer Struktur die Dinge in den Griff bekommen bis zu 8 Zeichen sind möglicherweise besser als die Verwendung von a, könnenchar[8]
jedoch nur 7 Zeichen verarbeiten oder müssen eine Zeichenfolge in denchar[9]
Puffer und dannmemcpy
an das Ziel kopieren .char
Zeigern laufen, bis sie eine Null erreichen. Das einzige, wofür nullterminierte Zeichenfolgen wirklich gut sind, sind Zeichenfolgenliterale, und selbst dort wäre ein mit variabler Länge codiertes Präfix wahrscheinlich besser. Für fast alles andere wäre es besser, Zeichenfolgen entweder mit einer Länge vorangestellt zu haben oder ein spezielles Präfix zu haben, das anzeigt, dass daschar*
wirklich so etwas iststruct stringInfo {char header[4]; char *realData; size_t length; size_t size;}
.Dies kann in vielen anderen Szenarien verwendet werden, in denen Sie nur einen Teil Ihrer ursprünglichen Zeichenfolge an das Ziel kopieren müssen. Mit strncpy () können Sie einen begrenzten Teil der ursprünglichen Zeichenfolge kopieren, im Gegensatz zu strcpy (). Ich sehe, dass der Code, den Sie erstellt haben, von publib.boulder.ibm.com stammt .
quelle
Das hängt von unserer Anforderung ab. Für Windows-Benutzer
Wir verwenden strncpy immer dann, wenn wir nicht die gesamte Zeichenfolge oder nur n Zeichen kopieren möchten. Strcpy kopiert jedoch die gesamte Zeichenfolge einschließlich der Beendigung des Nullzeichens.
Über diese Links erfahren Sie mehr über strcpy und strncpy und wo wir sie verwenden können.
über strcpy
über strncpy
quelle
strncpy ist eine sicherere Version von strcpy. Tatsächlich sollten Sie strcpy niemals verwenden, da es eine potenzielle Sicherheitsanfälligkeit bezüglich Pufferüberlauf darstellt, die Ihr System für alle Arten von Angriffen anfällig macht
quelle