Frage zu strtok() - Threadsicher?



  • Hallo,
    ich habe eine Frage zu der Funktion strtok() und wenn diese Funktion mittels beginthreadex mehrmals aufgerufen wird.
    Mich irritiert, daß diese Funktion sich ja beim ersten
    Aufruf den Inhalt merkt und man dann bei den Folgeaufrufen nur noch NULL
    als Parameter übergibt. Wenn nun mehrere Thread parallel strtok()
    aufrufen, merkt sich diese Funktion dann pro Thread ihren Inhalt oder
    gewinnt dann der jeweils zuletzt mit Werten befüllte strtok()-Aufruf?
    Was für alternativen gibt es so strtok() um einen String zu "splitten" ?

    Vielen Dank für die Antworten...



  • Was ist ein Thread?



  • strtok_r
    Aus der manpage:

    SYNOPSIS
    #include <string.h>

    char *strtok(char *str, const char *delim);

    char *strtok_r(char *str, const char *delim, char **saveptr);

    The strtok() function uses a static buffer while parsing, so it's not thread safe. Use strtok_r() if this matters to you.



  • linux_c89 schrieb:

    strtok_r

    Was ist denn das?



  • µngbd schrieb:

    linux_c89 schrieb:

    strtok_r

    Was ist denn das?

    Nichts was zum Standard gehört, aber da die Funktion existiert ist das wohl ein starkes Argument dafür, dass strtok() nicht thread save ist. (Steht ja auch in der Erklärung).



  • cooky451 schrieb:

    aber da die Funktion existiert ist das wohl ein starkes Argument dafür, dass strtok() nicht thread save ist. (Steht ja auch in der Erklärung).

    Nur dass C gar keine Threads kennt. Vom Standpunkt von C aus muss man erst fragen, um welche Art von "Threads" es geht. Wahrscheinlich hängt das vom verwendeten Betriebssystem ab. Da sind viele Möglichkeiten denkbar, deshalb halte ich es für verfehlt, eine GNU-Manpage vorzuzeigen, und daraus eine allgemeingültige Antwort zu extrapolieren.

    Trotzdem hast du wahrscheinlich recht.



  • Es hängt von der Implementierung ab. Unter Visual C++ ist strtok() z.B. ab Version 9 threadsafe. Die Antwort auf deine Frage findest du also in der Dokumentation deiner Toolchain...



  • Mit der Argumentation kannst du die Frage aber nie beantworten, da C ja nur den Standard kennt und der Standard eben keine Threads 😉

    dot schrieb:

    Unter Visual C++ ist strtok() z.B. ab Version 9 threadsafe.

    Lustigerweise warnen sie davor die Funktion "simultaneous" aufzurufen, aber Threads sind kein Problem oO



  • cooky451 schrieb:

    Lustigerweise warnen sie davor die Funktion "simultaneous" aufzurufen, aber Threads sind kein Problem oO

    Du liest die Doku der falschen Version 😉



  • dot schrieb:

    Du liest die Doku der falschen Version 😉

    Ich glaube du hast mich falsch verstanden. Das war nicht ironisch gemeint.

    msdn schrieb:

    However, calling this function simultaneously from multiple threads does not have undesirable effects.



  • Achso, naja es gibt ja verschiedene Arten von Threads. Wenn zwei Fibres im selben Thread die Funktion parallel verwenden würden, dann würde es vermutlich ein Problem geben.



  • Damit wird gemeint sein, dass man strtok nicht geschachtelt benutzen kann. Beispielsweise wird

    char data[]="foo,bar|baz,qux|quux,xyzzy";
    
    char *tok_outer, *tok_inner;
    
    for(tok_outer = strtok(data, "|"); tok_out; tok_outer = strtok(NULL, "|")) {
      for(tok_inner = strtok(tok_outer, ","); tok_inner; tok_inner = strtok(NULL, ",")) { /* Das geht NICHT! */
        /* ... */
      }
    }
    

    nicht das Gewünschte tun. Mit strtok_r (bzw. strtok_s unter Windows) ist es dagegen problemlos möglich.



  • Lol stimmt, das ist der offensichtlichere Weg wie man da Probleme bekommen kann 😃



  • Ok jetzt habe ich mit der strtok_s Funktion noch das Problem das es ab Windows Vista nicht funktioniert.

    strtok_s

    <string.h>

    Compatibility

    Windows 95, Windows 98, Windows 98 Second Edition, Windows Millennium Edition, Windows NT 4.0, Windows 2000, Windows XP Home Edition, Windows XP Professional, Windows Server 2003

    Gibt es irgendeine alternative für diese Funktion oder kann ich die Funktion irgendwie "nachschreiben"?



  • strtok_s() ist eine Funktion der CRT, die funktioniert überall wo die CRT läuft, also ganz sicher auch auf Vista und 7 😉



  • Warum bekomme ich dann die folgenden Fehlermeldungen:

    C:\Users\0x02\Programme und Source\strtok_s\project\main.c(21) : warning C4013: 'strtok_s' undefined; assuming extern returning int
    
    Linking...
    main.obj : error LNK2001: unresolved external symbol _strtok_s
    Debug/project.exe : fatal error LNK1120: 1 unresolved externals
    Error executing link.exe.
    


  • Code:

    #include <string.h>
    #include <stdio.h>
    
    char string1[] =
        "A string\tof ,,tokens\nand some  more tokens";
    char string2[] =
        "Another string\n\tparsed at the same time.";
    char seps[]   = " ,\t\n";
    char *token1,
         *token2,
         *next_token1,
         *next_token2;
    
    int main( void )
    {
        printf( "Tokens:\n" );
    
        // Establish string and get the first token: 
        token1 = strtok_s( string1, seps, &next_token1);
        token2 = strtok_s ( string2, seps, &next_token2);
    
        // While there are tokens in "string1" or "string2"
        while ((token1 != NULL) || (token2 != NULL))
        {
            // Get next token:
            if (token1 != NULL)
            {
                printf( " %s\n", token1 );
                token1 = strtok_s( NULL, seps, &next_token1);
            }
            if (token2 != NULL)
            {
                printf("        %s\n", token2 );
                token2 = strtok_s (NULL, seps, &next_token2); 
            }
        }
    }
    


  • Also bei mir (Visual Studio 2010) kompiliert das sowohl als C++ als auch als reines C ohne Probleme...



  • strtok_s gehört nicht zum C Standard, es ist eine Erweiterung von neueren MS-VC.
    Du verwendest eine Entwicklungsumgebung, die diese Funktion nicht unter diesem Namen anbietet, der Linker kann also den passenden Code nicht finden und genau das sagt er dir.



  • Der Fehlermeldung nach verwendet er eindeutig Visual C++. Es kann sich also eigentlich nur um eine uralte Version oder um ein Konfigurationsproblem handeln...


Anmelden zum Antworten