strtok дает ошибку сегментации - PullRequest
4 голосов
/ 05 марта 2010

Почему приведенный ниже код дает Seg. Ошибка в последней строке?

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

Как уже говорилось, чтение строк печатается без проблем, но почему нельзя разбить на токены?

Ответы [ 5 ]

17 голосов
/ 05 марта 2010

strtok изменяет свой первый аргумент, поэтому он должен быть изменяемым.

Может быть, ReadName () возвращает указатель на массив символов только для чтения. Можете ли вы показать нам свой ReadName ()function.

Если является причиной для seg-faullt, вы можете создать копию массива char, прежде чем передать ее в strtok, используя функцию strdup , например:

char *copy = strdup(m);
token = strtok(copy,'-');
....
....
free(copy); // free the copy once you are done using it.
2 голосов
/ 06 марта 2010

token=strtok(m,'-'); должно генерировать предупреждение компилятора, поскольку второй параметр strtok() - это const char *, указывающий на несколько разделителей, а не один char разделитель:

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

Код ASCII '-' равен 0x2D, ​​поэтому передача его в качестве второго параметра strtok() приведет к разыменованию strtok() адреса 0x0000002D, что вызовет ошибку сегмента или нарушение доступа в большинстве современных операционных систем.Чтобы исправить это, используйте строковый литерал вместо символьного литерала: token=strtok(m,"-");

Также существует проблема с тем, как распределяется возвращаемое значение ReadName(), о чем другие говорили в своих ответах.

0 голосов
/ 19 февраля 2016

Код ниже взят из лицензированной библиотеки обработки строк BS для C, которая называется zString .

https://github.com/fnoyanisi/zString

.можно увидеть, что strtok() (или в данном случае zstring_strtok()) полагается на static *char, чтобы сохранить последнее местоположение разделителя, и фактически изменяет исходную строку. достаточно хорошо объясняет разницу между char s[] и char *s.Итак,

char s[]="Test to pass strtok()"; /* this can be passed to strtok() */
char *m="Test to pass strtok()"; /* passing this will result in SIGSEGV */
0 голосов
/ 05 марта 2010

Вероятно, потому что ReadName() возвращает строку. Таким образом, присваивание делает m const char * и, следовательно, вы не можете изменить любое из его значений (изменить строку). Таким образом, когда 'strtok' пытается изменить 'm', Ошибка сегментации есть

Способ устранения:

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

OR

char *m = strdup(ReadName());
0 голосов
/ 05 марта 2010

Невозможно знать наверняка, не зная, на что указывает m. Но наиболее вероятная причина в том, что m указывает на постоянную память. Таким образом, вы можете распечатать его, но не можете написать.

strtok пишет в строку, поэтому она ошибочна, но printf только читает из нее, поэтому она не.

Попробуйте это

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