Why is this a simple segfault string assignment?

Ive got the following code:

#include <iostream> using namespace std; int main() { char* a = "foo"; char* b = "bar"; a = b; cout << a << ", " << b << endl; return 0; } 

This compiles and works, i.e. prints bar, bar . Now I would like to demonstrate that this is not copying a string. I would like to change b and show that a also changes. I came up with this simple code:

 #include <iostream> using namespace std; int main() { char* a = "foo"; char* b = "bar"; a = b; b[1] = 'u'; // ← just this line added cout << a << ", " << b << endl; return 0; } 

... but these are segfaults. What for? Interestingly, the following modification works just fine:

 #include <iostream> using namespace std; int main() { char* a = "foo"; char b[] = "bar"; // ← declaration changed here a = b; b[1] = 'u'; cout << a << ", " << b << endl; return 0; } 

Why is this not like the previous one? I guess I miss the important difference between pointer style and array initialization in array style.

+4
source share
6 answers

You cannot change the string constants that you get when you use the pointer-literal syntax, as in the first code examples.

See also this question: Is a string literal in C ++ created in static memory? .

+9
source

When you write this:

 char *b = "bar"; 

the compiler allocates an anonymous (unnamed) memory area for storing the string literal "bar". String literals cannot be changed, so the compiler (using the linker and the operating system) places the string literal in the portion of program memory that is write protected. When you try to change it, the operating system catches it and leads to a segmentation error.

(Your code is C ++, not C, but this is not relevant to this question.)

+6
source

When you write:

 char *foo = "bar"; 

What actually happens is that the bar is stored in a read-only memory segment. Therefore, it is unchanged. You get segfault because you are trying to change a read-only segment.

+2
source

You can also show that "a" was changed by printing the value of the pointer.

 #include <iostream> using namespace std; int main() { char* a = "foo"; char* b = "bar"; a = b; cout << (void*)a << ", " << (void*)b << endl; } 

This will print the address pointed to by 'a' and 'b'.
You must impose on 'void *' because the <<operator is overloaded for 'char *' to print a string, any other pointer will print the address.

+2
source

Theoretically, a string literal should not be bound to char *, only to 'const char *'. Then the compiler will stop you before you write the seg failure code.

+1
source

This difference is probably compiler specific. To demonstrate your use of the malloc point to allocate a buffer, copy the string to this buffer and remember to use it when you no longer need the string.

-1
source

All Articles