views:

1708

answers:

6

Hello all, 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?

+3  A: 

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
+1  A: 

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
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
A: 

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
A: 

Thanks for all the responses, I'm afraid I didn't see the results myself. My neighbour at work pointed this out and I was intrigued.

Mike B I'm pretty sure that is would be seen. And cheers for the efficiency point, I realise that this is rather contrived.

The efficiency point is not at all important - probably should have left it out. I still can't believe this really happens; it would break pretty much any code using std::string on that platform. There must be something missing from the description.
Michael Burr
Agree it's pretty unlikely; OP or his friend are mistaken. Wonder if they're doing something naughty like modifying a string literal.
fizzer
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
+1  A: 

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
+4  A: 

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
Thanks for this post. Very scary defect.
fizzer