Segmentierungsfehler bei Verwendung von strtok_r

Lesezeit: 4 Minuten

Benutzer-Avatar
Phulore R – Profil 2

Kann jemand erklären, warum ich im folgenden Beispiel einen Segmentierungsfehler erhalte?

#include <stdio.h>
#include <string.h>

int main(void) {
  char *hello = "Hello World, Let me live.";
  char *tokens[50];
  strtok_r(hello, " ,", tokens);
  int i = 0;
  while(i < 5) {
    printf("%s\n", tokens[i++]);
  }
}

Benutzer-Avatar
codaddict

Versuche dies:

#include <stdio.h>
#include <string.h>

int main(void) {
        char hello[] = "Hello World, Let me live."; // make this a char array not a pointer to literal.
        char *rest; // to point to the rest of the string after token extraction.
        char *token; // to point to the actual token returned.
        char *ptr = hello; // make q point to start of hello.

        // loop till strtok_r returns NULL.
        while(token = strtok_r(ptr, " ,", &rest)) {

                printf("%s\n", token); // print the token returned.
                ptr = rest; // rest contains the left over part..assign it to ptr...and start tokenizing again.    
        }
}
/*
Output:
Hello
World
Let
me
live.
*/

  • Dieses Beispiel gibt mir einen Segfault in der printf-Zeile. gdb print token zeigt 0xffffffffffffdad0 Bekomme auch diese beiden Warnungen, wenn ich proj1.c:33:2 kompiliere: Warnung: implizite Deklaration der Funktion ‘strtok_r’ [-Wimplicit-function-declaration] proj1.c:33:14: Warnung: Zuweisung macht Zeiger aus Integer ohne Umwandlung [enabled by default]

    – Nathan Schwermann

    1. Oktober 2012 um 0:48 Uhr

  • Entschuldigung, ich bin ein Neuling, warum sollte es nicht sein char *ptr = Hello; mit einem großen H? Außerdem sagt Aloks Antwort, dass das erste Mal, wenn der erste Parameter “tokenisiert” werden muss, und dann nachfolgende Aufrufe NULL sein müssen, aber es scheint, dass Ihr Beispiel es nur in die eine Richtung in der While-Schleife aufruft? Danke für den Code btw

    – SSH Dies

    17. Dezember 2012 um 22:48 Uhr


  • *ptr = hello; Weil hello bezieht sich auf char hello[]....

    – MrHIDEn

    9. Januar 2015 um 14:06 Uhr

  • Sie müssen anrufen strtok_r in einer Schleife. Das erste Mal, wenn Sie ihm die Zeichenfolge geben, die in Tokens umgewandelt werden soll, dann geben Sie sie an NULL als erster Parameter.
  • strtok_r nimmt ein char ** als dritter Parameter. tokens ist ein Array von 50 char * Werte. Wenn du passierst tokens zu strtok_r()was bestanden wird, ist a char ** Wert, der auf das erste Element dieses Arrays zeigt. Das ist in Ordnung, aber Sie verschwenden 49 der Werte, die überhaupt nicht verwendet werden. Du solltest haben char *last; und verwenden &last als dritter Parameter zu strtok_r().
  • strtok_r() ändert sein erstes Argument, also können Sie ihm nichts übergeben, was nicht geändert werden kann. Zeichenfolgenliterale in C sind schreibgeschützt, daher benötigen Sie etwas, das geändert werden kann: char hello[] = "Hello World, Let me live."; zum Beispiel.

  • Danke für die Antwort. Ich wünschte, SO darf mehrere Antworten als richtig markieren. 🙂

    – Phulore R – Profil 2

    9. Februar 2010 um 7:00 Uhr

  • @Scrub: freut mich, behilflich zu sein. Stellen Sie sicher, dass Sie meinen zweiten Punkt oben verstehen (ca char *tokens[50]; gleichwertig sein char ** bei Übergabe an eine Funktion).

    – Alok Singhal

    9. Februar 2010 um 7:04 Uhr

  • Rettete mich; +1, um mich daran zu erinnern, dass Param 1 nicht sein kann const char *. Für andere: Geben Sie keine Daten aus der .RODATA-Sektion ein. Oder: Probieren Sie aus, ob es mit funktioniert strcpy‘ing vorher in einen Temp-Puffer.

    – Joel

    25. Juni 2021 um 6:27 Uhr

Ein Haufen Dinge falsch:

  1. hello zeigt auf ein Zeichenfolgenliteral, das als unveränderlich behandelt werden muss. (Es könnte im Nur-Lese-Speicher leben.) Seitdem strtok_r mutiert seine Argumentzeichenfolge, die Sie nicht verwenden können hello damit.

  2. Du rufst an strtok_r nur einmal und initialisieren Sie Ihre nicht tokens Array, um auf irgendetwas zu zeigen.

Versuche dies:

#include <stdio.h>
#include <string.h>

int main(void) {
  char hello[] = "Hello World, Let me live.";
  char *p = hello;
  char *tokens[50];
  int i = 0;

  while (i < 50) {
     tokens[i] = strtok_r(p, " ,", &p);
     if (tokens[i] == NULL) {
        break;
     }
     i++;
  }

  i = 0;
  while (i < 5) {
    printf("%s\n", tokens[i++]);
  }

  return 0;
}

  • Danke für die Antwort. Ich wünschte, SO darf mehrere Antworten als richtig markieren. 🙂

    – Phulore R – Profil 2

    9. Februar 2010 um 7:01 Uhr

strtok_r versucht, Nullzeichen in hallo zu schreiben (was illegal ist, da es sich um eine konstante Zeichenfolge handelt).

Benutzer-Avatar
Anssi

Sie haben die Verwendung von strtok_r falsch verstanden. Bitte prüfen Sie das Beispiel und Dokumentation

Und versuchen Sie Folgendes:

#include <stdio.h>
#include <string.h>    

int main(void)
{
    char hello[] = "Hello World, let me live.";

    char *tmp;
    char *token = NULL;
    for(token = strtok_r(hello, ", ", &tmp);
        token != NULL;
        token = strtok_r(NULL, ", ", &tmp))
    {
        printf("%s\n", token);
    }

    return 0;
}

Benutzer-Avatar
SaphirSonne

Ich denke es könnte der sein char *tokens[50]; weil Sie es als Zeiger deklarieren, wenn es bereits ein Zeiger ist. Ein Array ist bereits bei der Deklaration ein Zeiger. Du meinst zu sagen char tokens[50];. Das sollte reichen.

1186290cookie-checkSegmentierungsfehler bei Verwendung von strtok_r

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

Privacy policy