Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Turning off COW in GCC

I've known for a while that GCC uses COW (Copy-On-Write) for std::string, making it impossible to use std::string in a multi-threaded program. But as far as I know C++11 prohibits an implementation from using COW, because threads are now defined by the standard, and move semantics pretty much obsolete the need for COW anyway.

Now, GCC 4.6 implements a great deal of the C++11 standard. Yet it seems that the implementation is still using COW semantics. This was brought to my attention by randomly occurring mysterious seg-faults in a multi-threaded application I wrote. I've confirmed this is, in fact, a COW issue via the following test code:

#include <iostream>
#include <string>
#include <cassert>
#include <thread>
using namespace std;

int main()
{
    std::string orig = "abc";
    std::string copy = orig;
    std::cout << (void*) orig.data() << ", " << (void*) copy.data() << endl;
    assert(orig.data() == copy.data());
}


Edit: Note the inclusion of the <thread> header here, proving this is a C++11 program. And here's a link to ideone confirming what I'm saying, (at least for GCC 4.5.1 which ideone uses)

I don't remember why, but for some reason I was under the impression that the std=c++0x flag would eliminate the COW semantics, but it doesn't. The assertion in the above code is successful, even with the --std=c++0x flag. So basically, as of GCC 4.6, std::string is still unusable in a multi-threaded application.

Is there any way to disable COW semantics? Or do I need to use std::vector<char> for now until GCC fixes this?

like image 997
Channel72 Avatar asked Sep 14 '12 19:09

Channel72


People also ask

Why COW was deemed ungood for std string?

The C++ standardization committee deemed that cost too high, the remaining advantages of COW too low, to continue supporting COW. So, the C++03 wordings that supported COW were removed; wording was introduced, especially a general O(1) complexity requirement for [] indexing, that disallowed COW; and.

Are C++ strings reference counted?

So, yes it is ref counted. Also, from the discussion here: Yes, std::string will be made non-reference counting at some point, but as a non-reference-counted string is valid in C++98 as well, one option would be to switch to a non-ref-counted string for both -std=c++98 and -std=c++11 modes.

How do you implement a copy on write?

To implement copy-on-write, a smart pointer to the real content is used to encapsulate the object's value, and on each modification an object reference count is checked; if the object is referenced more than once, a copy of the content is created before modification.


1 Answers

If you're going to pass a string across a thread boundary, do an explicit copy, in order to force it to be an independent string, then pass that across:

std::string a="bob";
std::string b(a.data(), a.length());

It's annoying to have to do this at all spots where things cross threads, but in my opinion it's easier than vector<char>.

like image 140
Michael Kohne Avatar answered Oct 11 '22 10:10

Michael Kohne