8

If I do:

const char* const_str = "Some string";

char* str = const_cast<char*>(const_str); // (1)

str[0] = "P"; // (2)

Where (which line) exactly is the undefined behavior ?

I've been searching a lot for this on SO but haven't found any explicit and precise answer (or at least, none that I could understand).

Also related: if I use an external library which provides this kind of function:

// The documentation states that str will never be modified, just read.
void read_string(char* str);

Is it ok to write something like:

std::string str = "My string";

read_string(const_cast<char*>(str.c_str()));

Since I know for sure that read_string() will never try to write to str ?

Thank you.

ereOn
  • 53,676
  • 39
  • 161
  • 238
  • Does this answer your question? [Is it allowed to cast away const on a const-defined object as long as it is not actually modified?](https://stackoverflow.com/questions/54504247/is-it-allowed-to-cast-away-const-on-a-const-defined-object-as-long-as-it-is-not) – user202729 Jan 19 '22 at 16:08

2 Answers2

9

Line (2) has undefined behaviour. The compiler is at liberty to place constants in read-only memory (once upon a time in Windows this would have been a "data segment") so writing to it might cause your program to terminate. Or it might not.

Having to cast const-ness away when calling a poorly-defined library function (non-const parameter which should be const) is, alas, not unusual. Do it, but hold your nose.

RobH
  • 3,199
  • 1
  • 22
  • 27
  • 6
    "Do it, but hold your nose." Consider doing it once in a wrapper function, so all the distributed call sites can at least avoid that ugliness. – Tony Delroy Apr 04 '11 at 08:07
  • Thank you very much for your answer. Do you have any source to strengthen your last claim ? I am designing a C++ wrapper around OpenSSL (which unfortunately suffers from serious interface inconsistencies) and I'd like to be sure that my code won't be a cause of undefined behavior. – ereOn Apr 04 '11 at 08:07
  • 2
    C++ standard Section 5.2.11#7 indicates that a *write operation* results in undefined behavior. Read operations should thus be safe. – edA-qa mort-ora-y Apr 04 '11 at 08:24
  • 1
    My last claim amounts to: Cast away const-ness if you trust the function that you are calling, so you'll have to satisfy yourself that the function is safe. const_cast isn't doing any magic under the hood; const_cast won't change the pointer or the data that it points to. You can't cause an error here by casting alone, but are removing a (usually) useful compiler safety check. – RobH Apr 04 '11 at 08:28
  • Thanks for the additional explanation and rationale. Very good answer. Both upvoted and accepted. – ereOn Apr 04 '11 at 08:54
-1

You are attempting to modify a constant string which the compiler may have put into a read-only section of the process. This is better:

char str[32];
strcpy(str, "Some string");
str[0] = "P";
trojanfoe
  • 120,358
  • 21
  • 212
  • 242
  • No offense, but that doesn't exactly answer my question: I know it is bad, and If my intent is to modify a string, I will not declare it `const` in the first place. The real question is more: "Do I really have to copy my string first to use it with a poorly designed interface or is the cast acceptable ?" – ereOn Apr 04 '11 at 08:04
  • As RobH has pointed out - it's on line (2) - the line where you modify the buffer that is potentially in read-only memory. – trojanfoe Apr 04 '11 at 08:06
  • 1
    @ereOn: the fact that C++ allows you to write `char* x = "abc"`, and hence is able to compile and run old C code without undefined behaviour, is evidence that there's no undefined behaviour until a write is actually attempted. – Tony Delroy Apr 04 '11 at 08:09