Reputation:
Why does the below code give Seg. Fault at last line?
char* m=ReadName();
printf("\nRead String %s\n",m); // Writes OK
char* token;
token=strtok(m,'-');
As said, read string prints w/o problem, but why cannot split to tokens?
Upvotes: 4
Views: 8506
Reputation: 1223
Code below is taken from a BSD licensed string processing library for C, called zString.
https://github.com/fnoyanisi/zString
Looking at the implementation of the function, you can see that strtok()
(or in this case zstring_strtok()
) relies on a static *char
to preserve the last location of the delimiter and actually modifies the original string.
char *zstring_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 string */
while(str[strlength])
strlength++;
/* find the first occurance of delim */
for (index=0;index<strlength;index++)
if (str[index]==delim[0]) {
found=1;
break;
}
/* if delim is not contained in str, return str */
if (!found) {
static_str = 0;
return str;
}
/* check for consecutive delimiters
*if first char is delim, return delim
*/
if (str[0]==delim[0]) {
static_str = (str + 1);
return (char *)delim;
}
/* terminate the string
* this assignmetn requires char[], so str has to
* be char[] rather than *char
*/
str[index] = '\0';
/* save the rest of the string */
if ((str + index + 1)!=0)
static_str = (str + index + 1);
else
static_str = 0;
return str;
}
This post explains the deifference between char s[]
and char *s
quite well. So,
char s[]="Test to pass strtok()"; /* this can be passed to strtok() */
char *m="Test to pass strtok()"; /* passing this will result in SIGSEGV */
Upvotes: 0
Reputation: 24328
token=strtok(m,'-');
should generate a compiler warning because the second parameter of strtok()
is a const char *
pointing to multiple delimiters, not a single char
delimiter:
char *strtok(char *str, const char *delim);
The ASCII code of '-'
is 0x2D, so passing it as the second parameter of strtok()
will cause strtok()
to dereference the address 0x0000002D, which will cause a segfault or access violation on most modern operating systems. To fix this, use a string literal instead of a character literal: token=strtok(m,"-");
There's also the issue of how the return value of ReadName()
is allocated, which others have addressed in their answers.
Upvotes: 2
Reputation: 12524
Its probably because ReadName()
return string. So, the assignment makes m
const char* and hence, you cannot alter any of its values (modify the string). So, when 'strtok' tries to modify 'm', Segmentation Fault is there
Remedy:
char *m = malloc(sizeof(char)*MAX);
strcpy(m, ReadName());
OR
char *m = strdup(ReadName());
Upvotes: 0
Reputation: 454940
strtok modifies its first argument, hence it should be modifiable.
Maybe ReadName() returns a pointer to a read-only char array.Can you show us your ReadName() function.
If that is the reason for seg-faullt, you can create a copy of the char array before you pass it to strtok using the strdup function like:
char *copy = strdup(m);
token = strtok(copy,'-');
....
....
free(copy); // free the copy once you are done using it.
Upvotes: 18
Reputation: 34128
It's impossible to know for sure without knowing what m
points to. But the most likely reason is that m
is pointing to readonly memory. So you can print it out, but you can't write to it.
strtok
writes to the string, so it's faulting, but printf only reads from it, so it isn't.
Try this
char* m=ReadName();
printf("\nRead String %s\n",m); // Writes OK
char temp = m[0];
m[0] = temp; // I'll bet you segfault here.
Upvotes: 0