6

I have used this line of code many times (update: when string was a parameter to the function!), however when I try to do it now I get a bus error (both with gcc and clang). I am reproducing the simplest possible code;

char *string = "this is a string";
char *p = string;
p++;
*p='x'; //this line will cause the Bus error
printf("string is %s\n",string);

Why am I unable to change the second character of the string using the p pointer?

theprole
  • 2,274
  • 23
  • 25
  • 1
    gcc has the option `-Wwrite-strings` that will warn you about changing literal strings by making them `const char[]`. Be aware that the Standard says literal strings are `char []` ("`read only char []`" in fact, but not `const`) and making them `const` makes your compiler (more) non-conformant. – pmg Nov 09 '10 at 00:00

1 Answers1

15

You are trying to modify read only memory (where that string literal is stored). You can use a char array instead if you need to modify that memory.

char str[] = "This is a string";
str[0] = 'S'; /* works */

I have used this line of code many times..

I sure hope not. At best you would get a segfault (I say "at best" because attempting to modify readonly memory is unspecified behavior, in which case anything can happen, and a crash is the best thing that can happen).

When you declare a pointer to a string literal it points to read only memory in the data segment (look at the assembly output if you like). Declaring your type as a char[] will copy that literal onto the function's stack, which will in turn allow it to be modified if needed.

mark4o
  • 58,919
  • 18
  • 87
  • 102
Ed S.
  • 122,712
  • 22
  • 185
  • 265
  • 1
    +1. Attempting to modify a string literal is undefined behaviour. It might appear to work but of course, it isn't guaranteed to. – dreamlax Nov 09 '10 at 00:01
  • "At best you would get a segfault" - actually, that bit's not quite true. Undefined behaviour is undefined and sometime that means it works as expected :-) There are plenty of embedded chips with no memory protection. Not saying your _answer_ is wrong since the question is tagged linux (so +1 for that), just that one particular point isn't necessarily true in all cases. – paxdiablo Nov 09 '10 at 00:02
  • @paxdiablo: Hence the "At best" part =) – Ed S. Nov 09 '10 at 00:04
  • i.e., you'd be lucky to get a seg fault. – Ed S. Nov 09 '10 at 00:04
  • Actually, at best (i.e., the best possible outcome), it would work perfectly :-) Although I would actually call that a bad outcome myself since it would propagate bad habits. – paxdiablo Nov 09 '10 at 00:12
  • I would consider that bad because you are now relying on unspecified behavior and you don't even know it(!). So yeah, agreed =) – Ed S. Nov 09 '10 at 00:16
  • 1
    A segfault is the best-case result. Worst-case is it silently "working" and changing the value of a constant string elsewhere in the program which happens to have the same contents and thus share the same storage. – R.. GitHub STOP HELPING ICE Nov 09 '10 at 00:34
  • That line of code was used when string was a parameter to the function!(in the past). That's why it worked, silly me. Thanks a lot anyway. – theprole Nov 09 '10 at 06:29
  • That would still be the same thing. If you were passing a pointer to a function and the pointer pointed to readonly memory you are still invoking undefined behavior. – Ed S. Nov 09 '10 at 07:47