-2

i have just started learning/exploring about const_cast and was experimenting with it when i found that after using const_cast,i get runtime error if i try to modify the data.

Basically i am dong something like

void main()
{
const char* str = "Hello";
char* mstr = const_cast<char*>(str);
mstr[1] = 'R';//<----- i get runtime exception on this line
}

is it happening because the string "Hello" is being stored somewhere in memory which cannot be modified.It would be great if someone can throw more light on this.

bourne
  • 1,083
  • 4
  • 14
  • 27
  • 2
    You are modifying data that isn't supposed to be modified, and tell the compiler which would deny you to do so _"I don't care"_. So why are you wondering? – πάντα ῥεῖ Mar 13 '16 at 08:54

3 Answers3

2

When you declare a string the way you've done, the compiler is allowed to do several things with it you may not expect. These include string merging (where multiple identical strings are actually only stored once), and storage in an area of memory that is write protected (note: it is not required to do either of these things, but it may).

In your case, it looks like the string got stored in write-protected memory. Telling the compiler to ignore this, by using const_cast, will trigger a CPU-exception, which will cause your program to terminate.

There is a simple solution though, which is to declare your string in a way that is modifyable:

char str [] = "Hello";
char* mstr = str;
mstr[1] = 'R'; 

Now it is an array you can legally modify as much as you want. No string merging will take place, and the data will not be stored in write-protected memory - and in fact you no longer need to const_cast either.

In general it is best not to use const_cast unless you know very, very clearly what you are doing. In my experience that mostly happens when interfacing to badly-written (usually C) APIs that take char * instead of const char *.

H. Guijt
  • 3,325
  • 11
  • 16
  • 1
    I didn't downvote this, but the OP's question pertains to `const_cast`, the proper usage of which and where he/she deviates from that usage is nowhere in this answer. Just a shot in the dark, but I'm going to guess that is likely the reason for the down-tick. – WhozCraig Mar 13 '16 at 09:18
  • Ah, lovely. So I get downvoted, then someone copies my answer almost verbatim (with the exact same information content), and it gets accepted and a +2. Thanks guys, that really helps my future desire to answer questions here... – H. Guijt Mar 13 '16 at 09:36
  • Say what? I have the current accepted answer and +2. The substance of my answer differs from yours, and I certainly did not copy it from you. Nor have I down-voted any answers to this question. – Peter Mar 14 '16 at 02:08
  • Not attacking you personally Peter; at the time I wrote that there was another answer that was accepted (not by you), which was at that time virtually identical to mine - same explanation and same source code. I wrote the first answer, and I think it addressed the problem and provided a solution in a reasonable way. It got voted down to -2, then the other guy came and copied it and got a +2. If it turns out that is 'normal' on this site then I'm done contributing. Let's see for now. – H. Guijt Mar 14 '16 at 08:17
2

A string literal is const, by definition, so any modification of one gives undefined behaviour.

You are using const_cast to create a non-const pointer to char (i.e. mstr) through which the compiler allows you to modify the string literal.

Doing that does not change the basic fact that modifying a string literal gives undefined behaviour. All the const_cast does is give you is a pointer, which you can use to modify the string literal without the compiler complaining. The compiler is not required to do anything to the string literal (e.g. store it in modifiable memory) to make that operation become valid. Modifying the string literal through mstr is therefore still undefined behaviour. One possible symptom of undefined behaviour is a runtime error.

Peter
  • 35,646
  • 4
  • 32
  • 74
1

Commonly, the data segment is read-write, since the values of vars can be altered of modified at the run time. This is in contrast to the read-only .rodata segment, which contains static constants rather than variables;

...
.file   "main.cpp"
.text
.Ltext0:
    .section    .rodata
.LC0:
.string "Hello"
.text
...

It also contrasts to the code segment .text segment, which is read-only on many architectures. Uninitialized data, both variables and constants, is instead in the BSS segment. The structure of executable file. Feel free to manually look through asm code, it's the most efficient way to understand what it really going on.

Pleeea
  • 362
  • 4
  • 12