开发者

Why is strtok causing a segmentation fault?

开发者 https://www.devze.com 2022-12-21 20:38 出处:网络
Why does the below code give Seg开发者_C百科. Fault at last line? char* m=ReadName(); printf(\"\\nRead String %s\\n\",m); // Writes OK

Why does the below code give Seg开发者_C百科. 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?


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.


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.


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.


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());


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 */
0

精彩评论

暂无评论...
验证码 换一张
取 消