Was sind einige der Nachteile bei der Verwendung von C-Style-Saiten?

8

Ich weiß, dass Pufferüberläufe eine potentielle Gefahr für die Verwendung von C-artigen Strings (char-Arrays) darstellen. Wenn ich weiß, dass meine Daten in meinen Puffer passen, ist es in Ordnung, sie trotzdem zu verwenden? Gibt es andere Nachteile von C-Style Strings, denen ich bewusst sein muss?

BEARBEITEN: Hier ist ein Beispiel, an das ich gerade arbeite:

%Vor%

Dieser Code nimmt Daten von einem FILE-Zeiger, der mit einem Befehl popen("df") erstellt wurde. Ich versuche, Linux-Befehle auszuführen und ihre Ausgabe zu analysieren, um Informationen über das Betriebssystem zu erhalten. Gibt es etwas Falsches (oder Gefährliches) beim Einstellen des Puffers auf eine beliebige Größe?

    
Bill the Lizard 23.11.2008, 14:33
quelle

16 Antworten

16

C-Zeichenfolgen fehlen die folgenden Aspekte ihrer C ++ - Gegenstücke:

  • Automatische Speicherverwaltung: Sie müssen ihren Speicher manuell reservieren und freigeben.
  • Zusätzliche Kapazität für die Verkettungseffizienz: C ++ - Strings haben oft eine größere Kapazität als ihre Größe. Dies ermöglicht es, die Größe ohne viele Neuzuweisungen zu erhöhen.
  • Keine eingebetteten NULs: Per Definition beendet ein NUL-Zeichen eine C-Zeichenfolge; C ++ - Zeichenfolge behält einen internen Größenzähler, so dass sie keinen speziellen Wert benötigen, um ihr Ende zu markieren.
  • Sinnvolle Vergleichs- und Zuweisungsoperatoren: Obwohl der Vergleich von C-String-Zeigern erlaubt ist, ist es fast immer nicht , was beabsichtigt war. In ähnlicher Weise erzeugt die Zuweisung von C-String-Zeigern (oder deren Übergabe an Funktionen) Besitzmehrdeutigkeiten.
efotinis 23.11.2008, 15:24
quelle
20

C-Strings haben einige Nachteile:

  1. Die Länge ist relativ teuer.
  2. Keine eingebetteten Null-Zeichen sind erlaubt.
  3. Die Signierung von Zeichen ist in der Implementierung definiert.
  4. Der Zeichensatz ist implementiert.
  5. Die Größe des Char-Typs ist die Implementierung definiert.
  6. Sie müssen separat verfolgen, wie jeder String zugewiesen ist und wie er frei sein muss, oder sogar, wenn er überhaupt frei sein muss.
  7. Es gibt keine Möglichkeit, auf ein Segment der Zeichenfolge als eine andere Zeichenfolge zu verweisen.
  8. Strings sind nicht unveränderbar, was bedeutet, dass sie separat synchronisiert werden müssen.
  9. Zeichenfolgen können zur Kompilierzeit nicht bearbeitet werden.
  10. Switch-Fälle können keine Zeichenfolgen sein.
  11. Der C-Präprozessor erkennt Zeichenfolgen in Ausdrücken nicht.
  12. Kann keine Zeichenfolgen als Vorlagenargumente (C ++) übergeben.
Walter Bright 24.11.2008 04:59
quelle
14

Die Länge, die in der konstanten Zeit zugänglich ist, ist in vielen Anwendungen ein schwerer Overhead.

    
Will Dean 23.11.2008 14:46
quelle
8

Sie wissen vielleicht, dass heute 1024 Bytes ausreichen, um irgendwelche Eingaben zu enthalten, aber Sie wissen nicht, wie sich die Dinge morgen oder nächstes Jahr ändern werden.

Wenn eine vorzeitige Optimierung die Wurzel allen Übels ist, sind magische Zahlen der Stamm.

    
John Dibling 23.11.2008 21:10
quelle
7

Die Speicherverwaltung usw., die benötigt wird, um die Zeichenfolge (char-Array) zu vergrößern, ist, wenn nötig, etwas langweilig, um neu zu erfinden.

    
activout.se 23.11.2008 14:38
quelle
6

Es gibt keine Möglichkeit, NUL-Zeichen (wenn Sie sie für etwas brauchen) in C-Stil-Zeichenfolgen einzubetten.

    
Tomalak 23.11.2008 14:41
quelle
6

Nun, um Ihr spezifisches Beispiel zu kommentieren, wissen Sie nicht, dass die von Ihrem Aufruf von df zurückgegebenen Daten in Ihren Puffer passen. Vertrauen Sie niemals un-sanatisierten Eingaben in Ihre Anwendung, selbst wenn sie von einer bekannten Quelle wie df stammen.

Wenn beispielsweise ein Programm mit dem Namen "df" irgendwo in Ihrem Suchpfad platziert wird, sodass es anstelle des System-df ausgeführt wird, könnte es dazu verwendet werden, Ihr Pufferlimit auszunutzen. Oder wenn df durch ein bösartiges Programm ersetzt wird.

Verwenden Sie beim Lesen einer Eingabe aus einer Datei eine Funktion, mit der Sie die maximale Anzahl der zu lesenden Bytes festlegen können. Unter OSX und Linux ist fgets () tatsächlich als char *fgets(char *s, int size, FILE *stream); definiert, so dass es auf diesen Systemen sicher verwendet werden könnte.

    
Brian C. Lane 23.11.2008 17:21
quelle
3

Probleme mit der Zeichencodierung treten auf, wenn Sie ein Byte-Array anstelle einer Zeichenfolge haben.

    
Tomalak 23.11.2008 14:36
quelle
3

In Ihrem speziellen Fall ist es nicht der C-String, der so gefährlich ist, wie das Lesen einer unbestimmten Menge von Daten in einen Puffer fester Größe. Verwenden Sie zum Beispiel nie gets (char *).

Wenn Sie jedoch Ihr Beispiel betrachten, scheint es überhaupt nicht korrekt zu sein - versuchen Sie Folgendes:

%Vor%

Dies ist eine vollkommen sichere Verwendung von C-Strings, obwohl Sie sich damit befassen müssen, dass line keine ganze Zeile enthält, sondern eher auf 1023 Zeichen gekürzt wurde (plus Null-Terminator).

    
Eclipse 23.11.2008 19:23
quelle
2

Ich denke, es ist in Ordnung, sie zu benutzen, die Leute benutzen sie seit Jahren. Aber ich würde lieber std :: string verwenden, wenn möglich 1) Sie müssen nicht jedes Mal so vorsichtig sein und können über Probleme Ihrer Domäne nachdenken, anstatt zu denken, dass Sie jedes Mal einen anderen Parameter hinzufügen müssen ... Speicherverwaltung und das ein bisschen Zeug ... es ist nur sicherer auf höherer Ebene programmieren ... 2) Es gibt wahrscheinlich noch andere kleine Probleme, die keine große Sache sind, aber immer noch ... wie die Leute schon erwähnt haben ... encoding, unicode ... all diese "verwandten" Sachen Leute, die std :: string gedacht haben ... :)

Aktualisieren

Ich habe ein halbes Jahr an einem Projekt gearbeitet. Irgendwie war ich blöd genug, um im Release-Modus vor der Auslieferung nicht zu kompilieren .... :) Nun, zum Glück gab es nur einen Fehler, den ich nach 3 Stunden gefunden habe. Es war ein sehr einfacher String Buffer Overrun.

    
badbadboy 23.11.2008 14:45
quelle
2

Keine Unicode-Unterstützung ist heutzutage Grund genug ...

    
Hoffmann 24.11.2008 00:05
quelle
0

c strings haben Möglichkeiten für einen Missbrauch, da dieser die Zeichenfolge scannen muss, um festzustellen, wo sie endet.

strlen - Um die Länge zu finden, scannen Sie die Zeichenfolge, bis Sie die NUL drücken oder auf geschützten Speicher zugreifen

strcat - muss scannen, um die NUL zu finden, um zu bestimmen, wo die Verkettung beginnen soll. Es gibt kein Wissen innerhalb einer c-Zeichenfolge, um festzustellen, ob ein Pufferüberlauf vorliegt oder nicht.

c-Zeichenfolgen sind riskant, aber in der Regel schneller als Zeichenfolgenobjekte.

    
EvilTeach 23.11.2008 14:44
quelle
0

Imho, der schwierigste Punkt von cstrings ist die Speicherverwaltung, weil Sie vorsichtig sein müssen, wenn Sie eine Kopie eines cstring übergeben müssen oder wenn Sie ein Literal an eine Funktion übergeben können, dh. Wird die Funktion die übergebene Zeichenfolge freigeben oder wird sie länger als der Funktionsaufruf beibehalten? Dasselbe gilt für Rückgabewerte von cstring.

Es ist also ohne großen Aufwand nicht möglich, cstring-Copys zu teilen. Dies endet in vielen Fällen mit unnötiger Kopie des gleichen cstring im Speicher.

    
quinmars 23.11.2008 15:28
quelle
0

Diese Frage hat wirklich keine Antwort.
Wenn Sie in C schreiben, was über Optionen haben Sie? Wenn Sie in C ++ schreiben, warum fragen Sie? Was ist der Grund, C ++ - Primitive nicht zu verwenden? Der einzige Grund, den ich denken kann, ist: C- und C ++ - Code verknüpfen und char * irgendwo in Schnittstellen haben. Manchmal ist es einfach, char * zu verwenden und stattdessen die ganze Zeit zurück und vorwärts zu konvertieren (besonders, wenn es wirklich 'guter' C ++ - Code ist, der 3 verschiedene C ++ - String-Objekttypen hat).

    
Ilya 23.11.2008 15:31
quelle
0

C-Saiten, wie viele andere Aspekte von C, geben Ihnen viel Raum, um sich aufzuhängen. Sie sind einfach und schnell, aber in der Situation unsicher, in der Annahmen wie der Null-Terminator verletzt werden können oder die Eingabe den Puffer überlaufen kann. Um sie zuverlässig zu machen, müssen Sie ziemlich hygenische Kodierungspraktiken beachten.

Früher gab es ein Sprichwort, dass die kanonische Definition einer Hochsprache "etwas mit besserer String-Handhabung als C" ist.

    
quelle
0

Eine weitere Überlegung ist, wer Ihren Code pflegen wird? Wie sieht es in zwei Jahren aus? Wird diese Person mit C-stlye-Saiten so vertraut sein wie du? Wenn die STL reifer wird, scheint es, dass die Leute mit STL-Streichern immer mehr vertraut sind als mit C-Style-Streichern.

    
JohnMcG 24.11.2008 00:36
quelle

Tags und Links