strtok donnant l’erreur de segmentation

Pourquoi le code ci-dessous donne-t-il Seg. Faute à la dernière ligne?

char* m=ReadName(); printf("\nRead Ssortingng %s\n",m); // Writes OK char* token; token=strtok(m,'-'); 

Comme dit, lire les empreintes de chaîne sans problème, mais pourquoi ne pas diviser en jetons?

strtok modifie son premier argument, il devrait donc être modifiable.

Peut-être que ReadName () renvoie un pointeur sur un tableau de caractères en lecture seule. Pouvez-vous nous montrer votre fonction ReadName ().

Si c’est la raison de seg-faullt, vous pouvez créer une copie du tableau de caractères avant de le transmettre à strtok à l’aide de la fonction strdup telle que:

 char *copy = strdup(m); token = strtok(copy,'-'); .... .... free(copy); // free the copy once you are done using it. 

token=strtok(m,'-'); devrait générer un avertissement pour le compilateur car le deuxième paramètre de strtok() est un caractère const char * pointant vers plusieurs délimiteurs, et non pas un seul délimiteur:

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

Le code ASCII de '-' est 0x2D. Par conséquent, si vous le passez comme deuxième paramètre de strtok() , strtok() déréférencera l’adresse 0x0000002D, ce qui provoquera un segfault ou une violation d’access sur la plupart des systèmes d’exploitation modernes. Pour résoudre ce problème, utilisez un littéral de chaîne au lieu d’un littéral de caractère: token=strtok(m,"-");

Il y a aussi la question de la façon dont la valeur de retour de ReadName() est allouée, ce que d’autres ont déjà abordé dans leurs réponses.

Il est impossible de savoir avec certitude sans savoir ce que m pointe vers. Mais la raison la plus probable est que m pointe vers la mémoire en lecture seule. Vous pouvez donc l’imprimer, mais vous ne pouvez pas y écrire.

strtok écrit dans la chaîne, donc c’est fautif, mais printf ne fait que la lire, donc ce n’est pas le cas.

Essaye ça

 char* m=ReadName(); printf("\nRead Ssortingng %s\n",m); // Writes OK char temp = m[0]; m[0] = temp; // I'll bet you segfault here. 

C’est probablement parce que ReadName() renvoie une chaîne. Ainsi, l’affectation fait m const char * et par conséquent, vous ne pouvez modifier aucune de ses valeurs (modifiez la chaîne). Donc, quand ‘strtok’ essaie de modifier ‘m’, l’ erreur de segmentation est présente

Remède:

 char *m = malloc(sizeof(char)*MAX); strcpy(m, ReadName()); 

OU

 char *m = strdup(ReadName()); 

Le code ci-dessous provient d’une bibliothèque de traitement de chaînes sous licence BSD pour C, appelée zSsortingng .

https://github.com/fnoyanisi/zSsortingng

En regardant l’implémentation de la fonction, vous pouvez voir que strtok() (ou dans ce cas zssortingng_strtok() ) s’appuie sur un caractère static *char pour conserver le dernier emplacement du délimiteur et modifier réellement la chaîne d’origine.

 char *zssortingng_strtok(char *str, const char *delim) { static char *static_str=0; /* var to store last address */ int index=0, strlength=0; /* integers for indexes */ int found = 0; /* check if delim is found */ /* delimiter cannot be NULL * if no more char left, return NULL as well */ if (delim==0 || (str == 0 && static_str == 0)) return 0; if (str == 0) str = static_str; /* get length of ssortingng */ while(str[strlength]) strlength++; /* find the first occurance of delim */ for (index=0;index 

Cet article explique assez bien la différence entre chars char s[] et char *s . Alors,

 char s[]="Test to pass strtok()"; /* this can be passed to strtok() */ char *m="Test to pass strtok()"; /* passing this will result in SIGSEGV */