#include<stdio.h>
void main()
{
char *p="nyks";
p[2]='n';
printf("%s",p);
}
This crashes with a SEGMENTATION FAULT. Can someone explain why?
#include<stdio.h>
void main()
{
char *p="nyks";
p[2]='n';
printf("%s",p);
}
This crashes with a SEGMENTATION FAULT. Can someone explain why?
It is undefined behavior to try to overwrite a string literal. C99 §6.4.5/6:
If the program attempts to modify such an array, the behavior is undefined.
This is restated in Appendix J.2 (undefined behavior).
If you instead do:
char p[] = "nyks";
you can allocate and initialize an automatic (stack) character array. In that case, it is perfectly fine to modify elements.
The standard dictates that literal strings are defined const
. You cannot change it.
The compiler places the literal in a readonly memory section. You can output the assembly and observe this. If you are using GCC it is done via the -s flag. It will place the string in a .rodata section.
String literals are not modifiable...
The ability to write char *p="nyks";
is actually a type system hole in C.
That translates to (essentially):
#include<stdio.h>
const char privatestring[5] = {"nyks"};
void main()
{
char *p = const_cast<char*>(privatestring);
p[2]='n';
printf("%s",p);
}
The compiler is allowed to put privatestring
somewhere where you only have read access. It does the const_cast for backward compatibility with programs written before that was a const keyword.
Other answers say the view from the standards perspective, but here's why it crashes.
Compilers typically put program literals – especially strings – in read-only memory. The memory is marked read-only by the OS, so any attempt to write to it will get trapped and, on your platform, this is what the segmentation fault indicates; an attempt to do an operation on some memory that isn't permitted. The other kind of crash associated with bad memory usage is a bus error, which typically indicates either a non-aligned memory access or a write to a page that isn't mapped at all. For C code, the difference is almost entirely academic (some other language implementations use these faults to help them manage memory).
Note that the trapping of writes to read-only is independent of the official semantics of the language. While you might have a char*
pointing to it, you still can't write it. Always treat program literals as if they are pointing to constant memory and you won't go wrong (that they aren't that by default is because of the need to support compatibility with older programs).