Gibt es eine sichere Version von strlen?

Lesezeit: 7 Minuten

Benutzer-Avatar
BЈовић

std::strlen verarbeitet keine c-Strings, die nicht mit \0 terminiert sind. Gibt es davon eine sichere Version?

PS Ich weiß, dass in c++ std::string anstelle von c-Strings verwendet werden sollte, aber in diesem Fall wird mein String in einem Shared Memory gespeichert.

BEARBEITEN

Ok, ich muss eine Erklärung hinzufügen.

Meine Anwendung erhält eine Zeichenfolge aus einem gemeinsam genutzten Speicher (der eine gewisse Länge hat), daher könnte sie als Array von Zeichen dargestellt werden. Wenn es einen Fehler in der Bibliothek gibt, der diesen String schreibt, dann wäre der String nicht nullterminiert und strlen könnte fehlschlagen.

  • …Na und tut den String beenden? Wenn es kein String-Endzeichen gibt und es keine andere Möglichkeit gibt, die Länge des Strings aus dem String selbst abzuleiten, müssen Sie die Länge irgendwo in einer separaten Variablen speichern.

    – Aasmund Eldhuset

    9. Mai 2011 um 10:14 Uhr

  • Wenn Sie die Länge nicht kennen und keine Möglichkeit haben, die Länge zu kennen, dann können Sie die Länge nicht bestimmen.

    – Leichtigkeitsrennen im Orbit

    9. Mai 2011 um 10:17 Uhr

  • Wie lang ist ein Stück Schnur? Doppelter Abstand von einem Ende zur Mitte.

    – johnsyweb

    9. Mai 2011 um 10:20 Uhr


  • Ändern Sie die Bibliothek, damit es keine Fehler gibt. Wenn das andere Programm während des Schreibens der Zeichenfolge abstürzen kann, ändern Sie das Protokoll so, dass ein Flag gesetzt wird, wenn es die Änderung erfolgreich abgeschlossen hat. Sie können die Länge einer beschädigten Zeichenfolge nicht kennen.

    – Jakow Galka

    9. Mai 2011 um 10:30 Uhr

  • EIN char Array, das nicht ist '\0' terminated ist kein String.

    – Keith Thompson

    23. Dezember 2013 um 4:38 Uhr

Sie haben hinzugefügt, dass sich die Zeichenfolge im gemeinsamen Speicher befindet. Das ist garantiert lesbar und von fester Größe. Sie können daher verwenden size_t MaxPossibleSize = startOfSharedMemory + sizeOfSharedMemory - input; strnlen(input, MaxPossibleSize) (achte auf den Aufpreis n in strnlen).

Dies wird zurückkehren MaxPossibleSize wenn es keine gibt \0 im gemeinsamen Speicher folgend input, oder die Zeichenfolgenlänge, falls vorhanden. (Die maximal mögliche Saitenlänge ist natürlich MaxPossibleSize-1falls das letzte Byte des gemeinsamen Speichers das erste ist \0)

  • Ja, das habe ich getan. Danke für die Antwort

    – BЈовић

    10. Mai 2011 um 9:54 Uhr

C-Strings, die nicht nullterminiert sind, sind keine C-Strings, sie sind einfach Arrays von Zeichen, und es gibt keine Möglichkeit, ihre Länge zu ermitteln.

  • Ok, aber gibt es eine sichere Alternative zu std::strlen?

    – BЈовић

    9. Mai 2011 um 10:31 Uhr

  • @unapersson: Da der Benutzer “sicher” in der unorthodoxen Bedeutung des Wortes “sicher” bedeutet, das von “sicheren” Zeichenfolgenfunktionen wie verwendet wird strlcpy, was du sagst stimmt nicht. Nun, es ist wahr, aber nicht relevant, da der Fragesteller nicht fragt, wie man die “Länge” von etwas ohne ein Null-Terminator findet, er fragt, wie man die Länge findet, wenn es eins hat, und nicht abstürzt, wenn es keins hat. Man kennt vielleicht die Pufferlänge, weiß aber nicht, ob sie ein Null-Byte enthält, und es ist möglich herauszufinden, welche und (falls es sich um eine Zeichenfolge handelt) die Länge.

    – Steve Jessop

    9. Mai 2011 um 11:21 Uhr


  • @Steve Was ist das für ein strlcpy, von dem du sprichst? Und meine Antwort bezog sich auf die ursprüngliche Frage.

    Benutzer2100815

    9. Mai 2011 um 11:28 Uhr

  • Der Nutzer? Der Fragesteller, meine ich. strlcpy eine BSD-Funktion ist, verwende ich sie als Beispiel für das Einzige, was ich habe je Bekannte Leute, über die man spricht, wenn sie über “sichere” String-Funktionen in C sprechen – etwas, das viel Zeit in Anspruch nimmt und es vermeidet, außerhalb dieser Grenze zu arbeiten.

    – Steve Jessop

    9. Mai 2011 um 11:28 Uhr


  • @unaperson … und es fehlte völlig an der modifizierten Frage, wo ich erklärt habe, wonach ich suche. @Steve Ein weiteres Beispiel ist sprintf

    – BЈовић

    9. Mai 2011 um 11:40 Uhr

Benutzer-Avatar
Dennis

Wenn Sie einen C-String als definieren

char* cowSays = "moo";

dann bekommst du autmagisch das ‘\0’ am ende und strlen würde 3 zurückgeben. Wenn Sie es wie folgt definieren:

char iDoThis[1024] = {0};

Sie erhalten einen leeren Puffer (und ein Array von Zeichen, die alle Nullzeichen sind). Sie können es dann mit dem füllen, was Sie möchten, solange Sie die Pufferlänge nicht überschreiten. Am Anfang strlen würde 0 zurückgeben, und sobald Sie etwas geschrieben haben, würden Sie auch die richtige Zahl erhalten strlen.

Sie könnten auch dies tun:

char uhoh[100];
int len = strlen(uhoh);

aber das wäre schlecht, weil Sie keine Ahnung haben, was in diesem Array ist. Es könnte ein Nullzeichen treffen, das Sie möglicherweise nicht treffen. Der Punkt ist, dass das Nullzeichen das ist definierter Standard Weise zu erklären, dass die Zeichenfolge fertig ist.

Kein Nullzeichen zu haben bedeutet per Definition dass die Saite noch nicht fertig ist. Wenn Sie dies ändern, wird das Paradigma der Funktionsweise der Zeichenfolge zerstört. Was Sie tun möchten, ist, Ihre eigenen Regeln aufzustellen. C++ lässt Sie das tun, aber Sie müssen selbst viel Code schreiben.

BEARBEITEN
Von Ihren neu hinzugefügten Informationen aus möchten Sie das Array durchlaufen und von Hand nach dem Nullzeichen suchen. Sie sollten auch eine Überprüfung durchführen, wenn Sie nur ASCII-Zeichen erwarten (insbesondere, wenn Sie alphanumerische Zeichen erwarten). Dies setzt voraus, dass Sie die maximale Größe kennen. Wenn Sie den Inhalt der Zeichenfolge nicht validieren müssen, können Sie eine der verwenden strnlen Funktionsfamilie:
http://msdn.microsoft.com/en-us/library/z50ty2zh%28v=vs.80%29.aspx
http://linux.about.com/library/cmd/blcmdl3_strnlen.htm

  • Vielen Dank. Ich suchte Strnlen

    – BЈовић

    9. Mai 2011 um 10:44 Uhr

  • @VJo: seit strnlen ist nicht Standard-C oder C++, das Sie vielleicht bevorzugen memchr (mit einer Überprüfung auf Null und einer Zeigersubtraktion). Oder es macht Ihnen vielleicht nichts aus strnlen ist in Windows und Posix.

    – Steve Jessop

    9. Mai 2011 um 11:27 Uhr


  • @Steve Ich wusste nicht, dass es kein Standard ist, aber da es Posix ist, ist es gut genug für mich (ich verwende Linux). Ich denke, es ist auch gut genug für Leute, die unter Windows programmieren, da es da ist

    – BЈовић

    9. Mai 2011 um 11:38 Uhr

size_t safe_strlen(const char *str, size_t max_len)
{
    const char * end = (const char *)memchr(str, '\0', max_len);
    if (end == NULL)
        return max_len;
    else
        return end - str;
}

Ja, seit C11:

size_t strnlen_s( const char *str, size_t strsz );

Gelegen in <string.h>

Benutzer-Avatar
Mattz

Holen Sie sich eine bessere Bibliothek oder überprüfen Sie die, die Sie haben – wenn Sie Ihrer Bibliothek nicht vertrauen können, dass sie tut, was sie verspricht, wie zum Teufel erwarten Sie dann Ihr Programm?

Das heißt, vorausgesetzt, Sie kennen die Länge des Puffers, in dem sich die Zeichenfolge befindet, worum geht es?

buffer[-1+sizeof(buffer)]=0 ;
 x = strlen(buffer) ; 
  • Machen Sie den Puffer größer als nötig und Sie können dann die Bibliothek testen.

    assert(x<-1+sizeof(buffer));
    

Benutzer-Avatar
Benutzer2023370

C11 enthält “sichere” Funktionen wie z strnlen_s. strnlen_s nimmt ein zusätzliches Argument für die maximale Länge (a size_t). Dieses Argument wird zurückgegeben, wenn nach der Überprüfung so vieler Zeichen kein Nullzeichen gefunden wird. Es gibt auch das zweite Argument zurück, wenn ein Nullzeiger bereitgestellt wird.

size_t strnlen_s(const char *, size_t);

Obwohl es Teil von C11 ist, wird empfohlen, dass Sie überprüfen, ob Ihr Compiler diese “sicheren” Funktionen zur Überprüfung von Grenzen über seine Definition von unterstützt __STDC_LIB_EXT1__. Außerdem muss ein Benutzer noch ein weiteres Makro setzen, __STDC_WANT_LIB_EXT1__zu 1vor dem Einschließen string.h, wenn sie beabsichtigen, solche Funktionen zu nutzen. Siehe hier für einige Stack Overflow-Kommentare zu den Ursprüngen dieser Funktionen und hier für die C++-Dokumentation.

GCC und Clang unterstützen auch die POSIX-Funktion strnlenund stellen Sie es innerhalb bereit string.h. Microsoft auch zur Verfügung stellen strnlen die auch darin zu finden sind string.h.

1385300cookie-checkGibt es eine sichere Version von strlen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy