Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexplained discrepancies when copying and modifying std::strings

In the following code, "situation 1" works as expected on all compilers tested, however "situation 2" it seems to behave differently based on the compiler used.

As an example MSVC has sit1 and sit2 produce the same results, however when using gcc/clang and libstdc++, the modification occurs to the original string and it's copy (sort of like a COW string) even though I'm building using the C++11 switch.

#include <iostream>
#include <string>

int main() {

   // situation 1
   {
      std::string x0 = "12345678";
      std::string x1 = x0;

      char* ptr = &x0[0] + 3;

      (*ptr) = ' ';

      std::cout << "1. x0: " << x0 << "\n";
      std::cout << "1. x1: " << x1 << "\n";

      if ((&x0[0]) == x0.data()) std::cout << "1. ptrs are equal\n";

   }

   // situation 2
   {
      std::string x0 = "12345678";
      std::string x1 = x0;

      char* ptr = const_cast<char*>(x0.data() + 3);

      (*ptr) = ' ';

      std::cout << "2. x0: " << x0 << "\n";
      std::cout << "2. x1: " << x1 << "\n";

      if ((&x0[0]) == x0.data()) std::cout << "2. ptrs are equal\n";
   }

   return 0;
}

GCC (6.1)

1. x0: 123 5678
1. x1: 12345678
1. ptrs are equal
2. x0: 123 5678
2. x1: 123 5678
2. ptrs are equal

MSVC (2015)

1. x0: 123 5678
1. x1: 12345678
1. ptrs are equal
2. x0: 123 5678
2. x1: 12345678
2. ptrs are equal

Is there any reason for the discrepancies in behavior between the various compilers - given that &x0[0] and .data() return the same address?

like image 912
Jacobi John Avatar asked Aug 16 '16 22:08

Jacobi John


1 Answers

Situation 2 causes undefined behaviour:

char* ptr = const_cast<char*>(x0.data() + 3);

(*ptr) = 'Z';

According to the specification of std::basic_string::data (C++14 [string.accessors]/3):

Requires: The program shall not alter any of the values stored in the character array.

In other words, you are not allowed to cast away the const and modify the string via the pointers returned by data() or c_str() .

like image 184
M.M Avatar answered Oct 29 '22 08:10

M.M