3

any thoughts on this would be appreciated:

std::string s1 = "hello";
std::string s2 = std::string(s1);

I'd now expect these two strings to be independent, i.e. I could append ", world" to s2 and s1 would still read "hello". This is what I find on windows and linux but running the code on a HP_UX machine it seems that s2 and s1 are the same string, so modifying s2 changes s1.

Does this sound absolutely crazy, anyone seen anything similar?

Evan Teran
  • 87,561
  • 32
  • 179
  • 238
christopherlumb
  • 141
  • 2
  • 4
  • Can you post a very short repro program? I find it hard to believe that something that basic is that broken. – Michael Burr Oct 09 '08 at 23:06
  • As a nit pick, your second line could simply be std::string s2(s1); There's no reason to create the extra temporary. – luke Oct 10 '08 at 12:27

5 Answers5

5

Although I could not reproduce the exact bug of the OP, I came across a similar bug in the HP-UX aCC compilers. I posted about it on the HP boards, and eventually got a response from HP. Basically their versions 3.xx (3.70, 3.73, 3.67, etc.) of aCC have messed up std::string construction. We had to move to the 6.xx versions of the compiler. The problem we had at the time was that there was not a 6.xx compiler available for PA-RISC machines, just Itanium. I believe that a 6.xx compiler was released for PA-RISC in September 2007.

The code that was giving the problem was:

#include <iostream>
#include <string>

class S : public std::string  // An extension of std::string
{
public:
  explicit S(const char* s)
    : std::string(s)
  {
  }
};

class N     // Wraps an int
{
public:
  explicit N(int n)
    : _n(n)
  {}
  operator S() const   // Converts to a string extension
  {
    return _n == 0 ? S("zero") : (_n == 1 ? S("one") : S("other"));
  }
private:
  int _n;
};

int main(int, char**)
{
  N n0 = N(0);
  N n1 = N(1);

  std::string zero = n0;
  std::cout << "zero = " << zero << std::endl;
  std::string one = n1;
  std::cout << "zero = " << zero
            << ", one = " << one << std::endl;

  return 0;
}

This was printing:
zero = zero
zero = one, one = one

In other words the construction of string one from n1 was clobbering another string completely (string zero).

NOTES:
To see the version of the compiler, type "aCC -V"
To see the type of machine, type "uname -m" (9000/800 ==> PA-RISC, ia64 ==> Itanium)

Andrew Stein
  • 12,880
  • 5
  • 35
  • 43
3

This must be a bug. std::string could do reference-counted strings as its implementation, but once it gets changed, it's supposed to "fork" the string.

Jim Buck
  • 20,482
  • 11
  • 57
  • 74
1

That sure sounds like a bug to me. Can anyone else who has access to HP/UX repro this?

You're saying that this program displays the same text on both lines?

#include <stdio.h>
#include <string>

int main () 
{
    std::string s1 = "hello"; 
    std::string s2 = std::string(s1);   // note: std::string s2( s1); would reduce the number of copy ctor calls

    s2.append( ", world");

    printf( "%s\n", s1.c_str());
    printf( "%s\n", s2.c_str());
}
Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • I tried to reproduce this on HP-UX using version 3.67 of HP's aCC compiler. It works correctly. However, I have come across severe problems with the aCC compiler's string construction. I will create a separate post about it. – Andrew Stein Oct 10 '08 at 15:11
1

Do the two strings actually change differently, or are you using some other comparison (such as the addresses returned by c_str())?

Some implementations of string don't copy the entire string when a copy is made so as to speed up the copying of long strings. If you attempt to make a change to either one, then the implementation should copy the string and make the appropriate changes (ideally as part of the same operation).

coppro
  • 14,338
  • 5
  • 58
  • 73
1

It would certainly be a defect. This example is verbatim from the C++ standard:

string s1("abc");
string::iterator i = s1.begin();
string s2 = s1;
*i = ’a’;  // Must modify only s1
fizzer
  • 13,551
  • 9
  • 39
  • 61