strdup() – was macht es in C?

Lesezeit: 8 Minuten

Benutzeravatar von Manoj Doubts
Manoj Zweifel

Was ist der Zweck der strdup() Funktion in C?

  • es gibt auch strdupa() (in der GNU C-Bibliothek), eine nette Funktion, die strdup() ähnelt, aber Speicher auf dem Stack allokiert. Ihr Programm muss den Speicher nicht explizit freigeben, wie im Fall von strdup(), er wird automatisch freigegeben, wenn Sie die Funktion verlassen, in der strdupa() aufgerufen wurde

    – dmitjugow

    31. Oktober 2008 um 13:05 Uhr

  • strdupa ist gefährlich und sollte nicht verwendet werden, es sei denn, Sie haben dies bereits festgestellt strlen ist sehr klein. Aber dann könnten Sie einfach ein Array mit fester Größe auf dem Stack verwenden.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    29. Dezember 2010 um 16:34 Uhr

  • @slacker google translate ist nicht hilfreich … Was tut strdup/strdupa bedeutet auf Polnisch?

    – haneefmubarak

    7. März 2015 um 16:47 Uhr

  • @haneefmubarak hier

    – anatolyg

    30. September 2015 um 17:02 Uhr

  • Hier ist der Unterschied zwischen strdup und strcpy stackoverflow.com/questions/14020380/strcpy-vs-strdup

    – Shiva Prakash

    21. August 2018 um 8:31 Uhr

Genau das, wonach es sich anhört, vorausgesetzt, Sie sind an die abgekürzte Art und Weise gewöhnt, in der C und UNIX Wörter zuweisen, es dupliziert Saiten 🙂

Denken Sie daran, dass es eigentlich nicht Teil des aktuellen (C17) ISO C-Standards selbst ist(a) (es ist eine POSIX-Sache), es macht effektiv dasselbe wie der folgende Code:

char *strdup(const char *src) {
    char *dst = malloc(strlen (src) + 1);  // Space for length plus nul
    if (dst == NULL) return NULL;          // No memory
    strcpy(dst, src);                      // Copy the characters
    return dst;                            // Return the new string
}

Mit anderen Worten:

  1. Es versucht, genügend Speicher zuzuweisen, um den alten String aufzunehmen (plus ein ‘\0’-Zeichen, um das Ende des Strings zu markieren).

  2. Wenn die Zuordnung fehlgeschlagen ist, wird es gesetzt errno zu ENOMEM und kehrt zurück NULL sofort. Einstellung von errno zu ENOMEM ist etwas malloc tut in POSIX, also müssen wir es nicht explizit in unserem tun strdup. Wenn du bist nicht POSIX-konform, ISO C schreibt die Existenz von nicht vor ENOMEM deshalb habe ich das hier nicht aufgenommen(b).

  3. Ansonsten hat die Zuordnung funktioniert, also kopieren wir den alten String in den neuen String(c) und geben Sie die neue Adresse zurück (für deren Freigabe der Anrufer irgendwann verantwortlich ist).

Denken Sie daran, dass dies die konzeptionelle Definition ist. Jeder Bibliotheksautor, der sein Gehalt wert ist, hat möglicherweise stark optimierten Code bereitgestellt, der auf den jeweiligen verwendeten Prozessor abzielt.

Eine andere Sache zu beachten, es sieht so aus ist derzeit in der C2x-Iteration des Standards geplant, zusammen mit strnduplaut Entwurf N2912 des Dokuments.


(a) Funktionen beginnen jedoch mit str und ein Kleinbuchstabe sind vom Standard für zukünftige Richtungen reserviert. Aus C11 7.1.3 Reserved identifiers:

Jeder Header deklariert oder definiert alle Bezeichner, die in seinem zugeordneten Unterabschnitt aufgeführt sind, und deklariert oder definiert optional Identifikatoren, die in der Unterklausel der zugehörigen zukünftigen Bibliotheksanweisungen aufgeführt sind.*

Die zukünftigen Richtungen für string.h kann gefunden werden in C11 7.31.13 String handling <string.h>:

Funktionsnamen, die mit beginnen str, memoder wcs und ein Kleinbuchstabe kann den Deklarationen in hinzugefügt werden <string.h> Header.

Sie sollten es also wahrscheinlich anders nennen, wenn Sie auf Nummer sicher gehen möchten.


(b) Die Änderung würde im Grunde ersetzen if (d == NULL) return NULL; mit:

if (d == NULL) {
    errno = ENOMEM;
    return NULL;
}

(c) Beachten Sie, dass ich verwende strcpy dafür, da dies die Absicht deutlich macht. In einigen Implementierungen kann die Verwendung schneller sein (da Sie die Länge bereits kennen). memcpy, da sie es ermöglichen, die Daten in größeren Blöcken oder parallel zu übertragen. Oder auch nicht 🙂 Optimierungs-Mantra Nr. 1: „Messen, nicht raten“.

Sollten Sie sich für diesen Weg entscheiden, würden Sie in jedem Fall so etwas tun:

char *strdup(const char *src) {
    size_t len = strlen(src) + 1;       // String plus '\0'
    char *dst = malloc(len);            // Allocate space
    if (dst == NULL) return NULL;       // No memory
    memcpy (dst, src, len);             // Copy the block
    return dst;                         // Return the new string
}

  • Es ist erwähnenswert, dass, wie die Beispielimplementierung von Pax andeutet, strdup(NULL) undefiniert ist und Sie kein vorhersehbares Verhalten erwarten können.

    – abschalten

    22. Mai 2009 um 10:14 Uhr

  • Ich denke auch, dass malloc() errno setzen würde, also sollten Sie es nicht selbst setzen müssen. Ich finde.

    – Chris Lutz

    8. Juni 2009 um 3:58 Uhr

  • @Alkot, strdup ist für Situationen, in denen Heap-Speicher für die Zeichenfolgenkopie zugewiesen werden soll. Ansonsten musst du es selber machen. Wenn du schon haben ein ausreichend großer Puffer (mallociert oder anderweitig), ja, verwenden strcpy.

    – paxdiablo

    28. Februar 2012 um 1:15 Uhr

  • @acgtyrant: Wenn Sie mit Standard den ISO-Standard meinen (den echten C-Standard), nein, er gehört nicht dazu. Es ist Teil des POSIX-Standards. Es gibt jedoch viele C Implementierungen die es bereitstellen, obwohl sie kein offizieller Teil von ISO C sind. Aber selbst wenn dies nicht der Fall wäre, sollte der Fünfzeiler in dieser Antwort mehr als ausreichend sein.

    – paxdiablo

    16. April 2014 um 10:37 Uhr

  • Guter Punkt, @chux, nur ISO-Mandate { EDOM, EILSEQ, ERANGE } wie erforderlich Fehlercodes. Habe die Antwort aktualisiert, um dies zu berücksichtigen.

    – paxdiablo

    30. Januar 2018 um 6:13 Uhr

Benutzeravatar von Patrick Schlüter
Patrick Schlüter

char * strdup(const char * s)
{
  size_t len = 1+strlen(s);
  char *p = malloc(len);

  return p ? memcpy(p, s, len) : NULL;
}

Vielleicht ist der Code etwas schneller als mit strcpy() als die \0 char muss nicht erneut gesucht werden (war schon mit strlen()).

  • Vielen Dank. In meiner persönlichen Umsetzung mache ich es noch “schlimmer”. return memcpy(malloc(len), s, len); Da bevorzuge ich den Absturz bei der Zuweisung eher als den NULL bei Zuordnungsfehler.

    – Patrick Schlüter

    30. Dezember 2010 um 21:00 Uhr

  • @tristopia Dereferenzierung NULL muss nicht abstürzen; es ist undefiniert. Wenn Sie sicher sein wollen, dass es abstürzt, schreiben Sie eine emalloc was ruft abort beim Scheitern.

    – David

    30. Dezember 2011 um 3:28 Uhr

  • Das weiß ich, aber meine Implementierung läuft garantiert nur auf Solaris oder Linux (durch die Natur der App).

    – Patrick Schlüter

    30. Dezember 2011 um 13:01 Uhr

  • @tristopia: Es ist gut, die Gewohnheit zu haben, die Dinge auf die beste Weise zu tun. Gewöhnen Sie sich an die Verwendung emalloc auch wenn es unter Solaris oder Linux nicht notwendig ist, damit Sie es in Zukunft verwenden werden, wenn Sie Code auf anderen Plattformen schreiben.

    – ArtOfWarfare

    28. Februar 2015 um 20:20 Uhr

Benutzeravatar von Chris Young
Chris Jung

Es macht keinen Sinn, die anderen Antworten zu wiederholen, aber bitte beachten Sie das strdup() kann aus C-Sicht machen, was es will, da es nicht Teil eines C-Standards ist. Es ist jedoch durch POSIX.1-2001 definiert.

  • Ist strdup() tragbar? Nein, nicht verfügbar in einer Nicht-POSIX-Umgebung (ohnehin trivial implementierbar). Aber zu sagen, dass eine POSIX-Funktion alles kann, ist ziemlich pedantisch. POSIX ist eine andere Standard das ist so gut wie C’s und noch beliebter.

    – PP

    9. Mai 2014 um 8:58 Uhr

  • @BlueMoon Ich denke, der Punkt ist, dass eine C-Implementierung, die keine Konformität mit POSIX beansprucht, möglicherweise immer noch a strdup als Erweiterung fungieren. Bei einer solchen Implementierung gibt es dafür keine Garantie strdup verhält sich genauso wie die POSIX-Funktion. Ich kenne keine solchen Implementierungen, aber eine legitime, nicht böswillige Implementierung könnte dies ermöglichen char *strdup(char *) aus historischen Gründen und lehnen Passierversuche ab const char *.

    Benutzer743382

    6. März 2015 um 22:19 Uhr

  • Was ist der Unterschied zwischen C-Standard und POSIX? Mit C-Standard meinen Sie, es existiert nicht in C-Standardbibliotheken?

    – Koray Tugay

    22. März 2015 um 11:35 Uhr

  • @KorayTugay Sie sind unterschiedliche Standards. Es ist besser, sie als unabhängig zu behandeln, es sei denn, Sie wissen, dass der Standard für eine bestimmte C-Funktion dem POSIX-Standard entspricht und dass Ihr Compiler/Ihre Bibliothek dem Standard für diese Funktion entspricht.

    – Matthäus Lesen

    23. März 2015 um 19:40 Uhr


Benutzeravatar von VonC
VonC

Aus strdup Mann:

Das strdup() Die Funktion soll einen Zeiger auf einen neuen String zurückgeben, der ein Duplikat des Strings ist, auf den gezeigt wird s1. Der zurückgegebene Zeiger kann übergeben werden free(). Ein Nullzeiger wird zurückgegeben, wenn die neue Zeichenfolge nicht erstellt werden kann.

Benutzeravatar von Karshit
Karscheiß

strdup() führt eine dynamische Speicherallokation für das Zeichen-Array einschließlich des Endzeichens ‘\0’ durch und gibt die Adresse des Heap-Speichers zurück:

char *strdup (const char *s)
{
    char *p = malloc (strlen (s) + 1);   // allocate memory
    if (p != NULL)
        strcpy (p,s);                    // copy string
    return p;                            // return the memory
}

Es gibt uns also einen anderen String, der mit dem durch sein Argument angegebenen String identisch ist, ohne dass wir Speicher zuweisen müssen. Aber wir müssen es später noch befreien.

Benutzeravatar von jussij
jussij

Es erstellt eine doppelte Kopie der Zeichenfolge, die durch Ausführen von a übergeben wird malloc und strcpy der übergebenen Zeichenfolge. Der mallocierte Puffer wird an den Aufrufer zurückgegeben, daher muss er ausgeführt werden frei auf den Rückgabewert.

Benutzeravatar von chqrlie
chqrlie

strdup und strndup sind in POSIX-konformen Systemen definiert als:

char *strdup(const char *str);
char *strndup(const char *str, size_t len);

Das strdup() -Funktion weist ausreichend Speicher für eine Kopie der Zeichenfolge zu strkopiert und gibt einen Zeiger darauf zurück.

Der Zeiger kann anschließend als Argument für die Funktion verwendet werden free.

Wenn nicht genügend Speicherplatz vorhanden ist, NULL zurückgegeben wird und errno ist eingestellt auf
ENOMEM.

Das strndup() Funktion kopiert höchstens len Zeichen aus der Zeichenfolge str immer null, das den kopierten String beendet.

1427160cookie-checkstrdup() – was macht es in C?

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

Privacy policy