我正在开发一个在Linux上运行的多线程程序(用G ++ 4.3编译),如果你搜索一下,你会发现很多关于std :: string与GCC不是线程安全的可怕故事.这可能是因为它在内部使用了写入时复制,这会对像Helgrind这样的工具造成严重破坏.
我做了一个小程序,将一个字符串复制到另一个字符串,如果你检查两个字符串,它们都共享相同的内部_M_p指针.当一个字符串被修改时,指针会发生变化,因此写入时复制的东西工作正常.
我担心的是,如果我在两个线程之间共享一个字符串(例如将它作为一个对象传递给两个线程之间的线程安全数据队列)会发生什么.我已经尝试使用'-pthread'选项进行编译,但这似乎没有太大区别.所以我的问题:
我似乎无法找到明确的答案,所以我希望你们能帮助我..
编辑:
哇,在这么短的时间内,这是很多答案.谢谢!当我想禁用COW时,我肯定会使用Jack的解决方案.但现在主要问题变成:我真的必须禁用COW吗?或者COW线程的"簿记"是否安全?我目前正在浏览libstdc ++源代码,但这需要相当长的时间来弄清楚......
编辑2
好了,浏览了libstdc ++源代码,我在libstd ++中找到了类似的东西--v3/include/bits/basic_string.h:
_CharT*
_M_refcopy() throw()
{
#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
if (__builtin_expect(this != &_S_empty_rep(), false))
#endif
__gnu_cxx::__atomic_add_dispatch(&this->_M_refcount, 1);
return _M_refdata();
} // XXX MT
Run Code Online (Sandbox Code Playgroud)
因此,参考计数器肯定有一些关于原子变化的东西......
结论
我将sellibitze的评论标记为答案,因为我认为我们已经得出结论,这个领域目前尚未解决.为了规避COW的行为,我建议Jack Lloyd回答.谢谢大家的有趣讨论!
假设我有以下字符串:
string str1 = "Hello World!";
string str2 = str1.SubString(6, 5); // "World"
Run Code Online (Sandbox Code Playgroud)
我希望在上面的例子str2中不复制"World",但只是最终成为一个新的字符串,指向相同的内存空间,只是它以6的偏移量和5的长度开始.
实际上我正在处理一些可能非常长的字符串,并且由于性能原因我对它在幕后的工作方式感兴趣.我不熟悉IL调查此事.
在我的应用程序中,我创建了char*这样的:
class sample
{
public:
char *thread;
};
sample::sample()
{
thread = new char[10];
}
sample::~sample()
{
delete []thread;
}
Run Code Online (Sandbox Code Playgroud)
我在代码中做了正确的事吗?
我实际上在谷歌检查了这一点,但我通常发现相反.C++中是否存在使用字符串库字符串而不是C字符串或某种字符数组的任何缺点?除了可能有点慢?
随意给我一个傻瓜,但是我已经搜索过并且找不到任何东西(但是我确定有人问过)