0

I am getting a segmentation fault while running the following code :-

char *p ="Hello";
*p = 'M';

what I intended was to replace the first character of the string "Hello" with 'M'. But I'm getting segmentation fault. What could be the reason?

Indra Yadav
  • 600
  • 5
  • 22
user3284709
  • 13
  • 1
  • 5

3 Answers3

2

It's undefined behaviour. For compatibility with old C code, C++ compilers have let you point a non-const pointer at a string literal (e.g. your "Hello"), but you can not write through them portably.

It's best to use:

const char* p = "Hello";        // if you really need a pointer, probably so you
                                // can move it within the text, point it at other
                                // text, set it to a NULL sentinel after use...

const char[] hello = "Hello";   // if you're really only interested in the text
Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • No offense, and UB is definitely the precise way of saying this. But I am really sick of seeing people saying "UB" everywhere, when it's much simpler and easier to just say "you are not allowed to do this", especially to a beginner. – WiSaGaN Feb 10 '14 at 10:35
  • @WiSaGaN: no offense taken ;-). Pros and cons either way, but I do feel I've done both: "but you can not write through them portably". – Tony Delroy Feb 10 '14 at 10:39
  • "portably" ruins it again. :D – WiSaGaN Feb 10 '14 at 10:40
  • @WiSaGaN: does it just... you do realise that some compilers still in common use actually support writable string literals - e.g. Microsoft's via a commmand line switch? From memory, I think there's even explicit control over whether any sharing of buffers should be done. Undefined behaviour doesn't mean "you are not allowed to do this" if an implementation decides to support it. Awful idea to depend on it though! :-) – Tony Delroy Feb 10 '14 at 10:48
  • "Portably" is as precise as "UB". But too pedantic for my taste, and hard to grasp for beginner. That's what I mean. ;-) – WiSaGaN Feb 10 '14 at 10:51
1

Any string literal in C++ and C (for example "Hello" in your code) is of type const char [6] and can implicitly be assigned to any const char * value:

const char * str="Hello";

indicating that it resides in memory marked as read-only by the operating system (you should have gotten a compiler warning). Therefore an exception will be thrown when you try to change that memory location.

The reason why the compiler puts this in read-only memory is because you may be using another identical (or even similar) string literal "Hello" in a different part of your code. By marking the memory location of the string literal as read-only, the compiler only needs to store the string literal once in memory.

Note also, that the C++ standard does not require the compiler putting the string literal into read-only memory, it just says that modifying a string literal is undefined behaviour. In practice however, a string literal is stored in read-only memory on any modern operating system or compiler.

hogliux
  • 231
  • 1
  • 4
  • 18
  • 1
    The type is actually `const char[6]` – juanchopanza Feb 10 '14 at 10:35
  • Yes you are right. However casting to `const char *` is always implicitly possible. I'll edit my post – hogliux Feb 10 '14 at 10:37
  • "you may be using another identical string" - true, but interestingly the compiler's allowed to share the memory even for non-identical strings, such as "Hello Hello" and "Hello", where the latter may be found in the second word of the former (while still sharing NUL terminators). – Tony Delroy Feb 10 '14 at 10:41
  • OK just updated my answer. – hogliux Feb 10 '14 at 10:42
0

The compiler is putting the string for "Hello" into a read-only memory segment and giving you a pointer to it. The fact that you're allowed to assign the pointer to a char* is done for backwards compatibility. C++ states that it's undefined behaviour.

If you want to alter the string then declare it like this :

char p[]="Hello";
Sean
  • 60,939
  • 11
  • 97
  • 136