0

I'm trying to use strstr() to find a substring in a string. Using char[] works only, char* is not working, gives segmentation fault.

So this one is working:

int main() {
    char str[] = "apple apple peach";
    char *p;

    p = strstr(str, "peach");
    if (p!= NULL) {
        strncpy(p, "apple", 5);
    }
    return 0;
}

But this one is not working:

int main() {
    char *str = "apple apple peach";
    char *p;

    p = strstr(str, "peach");
    if (p!= NULL) {
        strncpy(p, "apple", 5);
    }
    return 0;
}

This one is neither:

int main() {
    char *str = "apple apple peach";
    char *peach = "peach";
    char *p;

    p = strstr(str, peach);
    if (p!= NULL) {
        strncpy(p, "apple", 5);
    }
    return 0;
}

And neither this one:

int main() {
    char *str = "apple apple peach";
    char peach[] = "peach";
    char *p;

    p = strstr(str, peach);
    if (p!= NULL) {
        strncpy(p, "apple", 5);
    }
    return 0;
}

Is that a known bug or feature?

Saurav Sahu
  • 13,038
  • 6
  • 64
  • 79
Janekx
  • 631
  • 6
  • 21

3 Answers3

5

Your problem is not with strstr, it's with strncpy. In the pointer case, you're using strncpy to try to write to string literal, which is constant.

jamesdlin
  • 81,374
  • 13
  • 159
  • 204
3

string-literal is not safe to modify! The one with char[] was successful only because strncpy(p, "apple", 5); modified the copied version of string-literal, not the string-literal itself. The relevant paragraphs in the standard read:

6.4.5, paragraph 6

... The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence...

6.4.5, paragraph 7

... If the program attempts to modify such an array, the behavior is undefined.

In short, string-literal is (conceptually) replaced with an array, and it's not safe to modify this. Note that string-literal is not necessarily const-qualified, although MSVC++ seems to mandate that string-literal is const char * or something that's const-qualified.

1

It has nothing to do with strstr: it works as expected. The crash happens in strcpy, when you attempt to modify memory allocated to string literal. This is undefined behavior.

The key to solving this problem is placing the data into memory that allows writing. Your first program does so by declaring str an array:

char str[] = "apple apple peach";

That is not UB, so the program runs to completion. Another alternative would be to allocate str in dynamic memory, like this:

char *str = malloc(20);
strcpy(str, "apple apple peach");
char *p;
p = strstr(str, "peach");
if (p!= NULL) {
    strncpy(p, "apple", 5);
}
free(str);
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523