Richard Heck wrote:

> Can you explain in language I can understand why simply /reading/ this
> variable
> in separate threads could cause this kind of problem? I'm very confused.

I guess the basic principle how copy-on-write works is clear? If not, see 
e.g. http://en.wikipedia.org/wiki/Copy-on-write.

The problem is not the read access. This is safe. The problem is write 
access and can be illustrated by the following code:

std::string s1("foo");
std::string s2(a);
std::string s3 = s1;

After these three lines all strings share the same pointer to the rep 
object:

assert(s2._M_rep() == s1._M_rep());
assert(s3._M_rep() == s1._M_rep());

are both true. To understand the following, we need to know that 
std::basic_string::_M_p is a member variable pointing to the actual 
character data, and std::basic_string::_M_rep() returns a pointer to an 
object of type std::basic_string::_Rep which holds the metadata. The only 
relevant member in our case is std::basic_string::_Rep::_M_refcount which 
contains 0 if this particular _Rep object is used by one std::basic_string 
object. The actual implementation is much more complicated (and this is also 
the reason I used the accessor _M_rep() and not a member variable for thsi 
illustration), but this is not needed to understand the basic problem. At 
this point we know that

assert(s1._M_rep()->_M_refcount == 2);


After changing one string (e.g. a):

s1 = "bar";

the following conditions are true:

assert(s2._M_rep() == s3._M_rep());
assert(s2._M_p     == s3._M_p);
assert(s1._M_rep() != s2._M_rep());
assert(s1._M_p     != s2._M_p);
assert(s1._M_rep()->_M_refcount == 0);
assert(s2._M_rep()->_M_refcount == 1);

Now imagine that s1 is used in thread a and s2 is used in thread b => there 
you have your race condition: Changing the object s1 in thread a which is 
not used in thread b does still modify internal data of object s2 which is 
used in thread b. If this happens while s2 is being deleted or altered in 
thread b you are in trouble and will likely see a crash. Of course the 
chance for this to happen is very very small, so I am actually not surprised 
that others could not reproduce the crash.


Georg





Reply via email to