Wie regeln Funktionen wie "strtok()" die Speicherallokation?



  • Hallo,

    ich kann ja mit strtok einen String in mehrere Teile teilen:

    char *string="Das ist ein Test.";
    char *target=strtok(string," "); // target = "Das"
    target=strtok(NULL," ");         // target = "ist"
    target=strtok(NULL," ");         // target = "ein"
    target=strtok(NULL," ");         // target = "Test."
    

    Ich kann der Funktion später NULL als Parameter übergeben, dann wird einfach der alte String weiterbearbeitet. Das setzt voraus, dass der alte String gespeichert wird.

    1. Wie funktioniert das? Ich glaube mal gelesen zu haben, dass Variablen, die lokal in einer Funktion sind, nach dem Funktionsaufruf verfallen, verwendet strtok also einen globalen Buffer?

    2. strtok() muss diesen globalen Buffer mit malloc reservieren?! Aber wer ruft vor Programende free() auf? Ich nicht...

    3. Gibt es eine Alternative zu diesem Quellcode:

    char *s1="abcdefghijklmnopqrstuvwxyz"; // der Inhalt ist für dieses Beispiel nicht relevant
    char *s2;
    int i;
    
    for(i=0;s1[i] != '\0';i++) 
    {
       s2[i]=s1[i];
    }
    

    Ich weiß, dass ich für diese Funktion besser "strcpy" verwenden sollte, aber darum geht es nicht. Es geht darum, dass ich hier versuche, einen nicht allokierten Speicher zu beschreiben. Wenn bei strtok nämlich kein Speicher allokiert wird, dann muss das so wie hier funktionieren, d.h. es wird einfach auf den char-pointer geschrieben. Das gibt aber Probleme, denke ich, weil dem char-pointer per default vom Compiler kein oder nur wenig Speicherplatz zugewießen wird, d.h. es wird dann im schlimmsten Fall versucht, den Speicher zu überschreiben, was zum Absturz des Programms führt.



  • erklärt mir das mal bitte schrieb:

    char *string="Das ist ein Test.";
    char *target=strtok(string," "); // target = "Das"
    target=strtok(NULL," ");         // target = "ist"
    target=strtok(NULL," ");         // target = "ein"
    target=strtok(NULL," ");         // target = "Test."
    

    Ich kann der Funktion später NULL als Parameter übergeben, dann wird einfach der alte String weiterbearbeitet. Das setzt voraus, dass der alte String gespeichert wird.

    1. Wie funktioniert das? Ich glaube mal gelesen zu haben, dass Variablen, die lokal in einer Funktion sind, nach dem Funktionsaufruf verfallen, verwendet strtok also einen globalen Buffer?

    Keinen Buffer, nur einen Zeiger. Und der dürfte eher static als global sein, außer strtok braucht den ja keiner.

    2. strtok() muss diesen globalen Buffer mit malloc reservieren?! Aber wer ruft vor Programende free() auf? Ich nicht...

    Es gibt keinen Buffer.

    strtok schreibt übrigens in den übergebenen String (es überschreibt die Trennzeichen mit '\0'), so dass dein Programm undefiniertes Verhalten hat, da ein Stringliteral nicht modifiziert werden darf.

    Der Rest hat sich damit wohl erledigt, ich hoffe ich muss nicht detailliert erklären, dass das Beispiel in Frage 3 totaler Käse ist.



  • Wie würdest du mein Beispiel lösen. Einzige Bedingung: kein malloc oder free.

    Und strtok braucht keiner? Welche Funktion verwenden denn dann die ganzen Browser und curl-libs und wie sie alle heißen, um urls aufzusplitten ("http:/", "www.", seitenname, ".de" usw.)



    1. ja, ein globale Puffer oder eine globale Variable können verwendet worden sein. Da der Standard nur schreibt nur das Verhalten von strtok vor, aber nicht, wie es implemntiert wird, sind die Vermutungen hinfällig.

    2. Variablen müssen nicht zwingen mit alloc oder new angelegt worden sein.



  • erklärt mir das mal bitte schrieb:

    Wie würdest du mein Beispiel lösen. Einzige Bedingung: kein malloc oder free.

    Ich kann Probleme lösen, aber keine Beispiele. Was genau möchtest du haben?

    Und strtok braucht keiner?

    Woher hast du das? Hab ich das geschrieben? Ich mein, das kann ja sein, ich hab jedenfalls noch nie strtok auch nur in Erwägung gezogen, aber das muss ja nichts heißen.



  • Bashar schrieb:

    erklärt mir das mal bitte schrieb:

    Wie würdest du mein Beispiel lösen. Einzige Bedingung: kein malloc oder free.

    Ich kann Probleme lösen, aber keine Beispiele. Was genau möchtest du haben?

    Und strtok braucht keiner?

    Woher hast du das? Hab ich das geschrieben? Ich mein, das kann ja sein, ich hab jedenfalls noch nie strtok auch nur in Erwägung gezogen, aber das muss ja nichts heißen.

    Ich möchte, dass du mir bitte zeigst, wie du mein Beispiel lösen würdest, also:

    einen string in einen anderen kopieren, ohne malloc, free oder str(n)cpy oder sonstige stdlib-funktionen zu verwenden. danke.



  • in C.



  • Wie du (durch ausprobieren) sicherlich schon herausgefunden hast, verändert strtok den Eingabestring. Unter dieser Voraussetzung reicht ein statischer Pointer auf den Eingabestring aus, um ihn zu zerlegen. Ganz ohne malloc . Und ohne free . Und sogar in C! Der Pointer wird beim ersten strtok gesetzt und bei jedem weiteren Aufruf verschoben.

    Edit: Und schon wieder zu spät... Bashar hat ja schon alles erklärt



  • char * strtok ( char * str, const char * delimiters )
    { static char *string = NULL;
      ...
      if (str != NULL) 
        string = str;
    
      .....
    }
    

    Oder sieh selber nach: strtok.c


Anmelden zum Antworten