Qt4 C++:来自多个线程的QString变量使用崩溃
Qt4 C++: QString variable usage from multiple threads crashes
我的Qt4代码使用一些QThread实例,这些实例在包含一些QString字段的公共数据结构上操作。它可以归结为以下内容:
我的数据结构:
class My : public QObject{
Q_OBJECT
public:
QString foo;
};
线程实现:
class Thr : public QThread{
public:
My* my;
protected:
void run(){
while (true){
QString copy = my->foo;
QString bar = copy.toUpper();
my->foo = bar.toLower();
}
}
};
这是我为研究这个问题而写的测试应用程序。当然,它并没有做任何实际有用的事情:)
如果我初始化My
的一个实例,并用该实例启动一个线程,那么一切都很好。但是,当我用相同的My
实例启动第二个实例时,它会崩溃,出现不同的消息,看起来像是堆/堆栈/任何损坏。
这正常吗?我知道一般的多线程问题,也知道Qt的QMutex,它可以避免这个问题。但就我正确理解Qt文档而言,我可以这样使用它。我不会同时对同一个QString实例进行操作(可能是因为一些奇特的隐式共享机制,但文档中指出这对用户来说是完全透明的?!)。
如前所述,我的问题不是如何重写代码,而是"从Qt4开始,隐式共享类可以像任何其他值类一样安全地跨线程复制。它们是完全可重入的。隐式共享真的是隐式的。"(http://qt-project.org/doc/qt-4.8/threads-modules.html)我误解了。
如注释中所述,您可能正试图从不同的线程写入相同的数据。我写"可能"只是因为你没有分享你的QThread
子类的用法。
正如注释中所指出的,对于像Object
子类这样内部有QString
的类,C++标准甚至不能保证赋值是线程安全的。
您可以根据提示使用std::atomic
,尽管它从C++11开始才可用。一个更交叉的解决方案是在您的场景中使用QMutex
,或者可能更好地将RAII解决方案与QMutexLocker
一起使用,后者将自动为您解锁。所以你会像下面的代码一样。
class Thr : public QThread{
public:
My* my;
QMutex mutex; // <--- first addition
protected:
void run(){
while (true){
QString copy = my->foo;
QString bar = copy.toUpper();
QMutexLocker locker(&mutex); // <--- second addition
my->foo = bar.toLower();
}
}
};
当然,推荐的解决方案取决于其他因素,例如,你也可以根据手头的确切用例重新设计你的程序,不使用指针,等等
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 将数组的地址分配给变量并删除
- 为"adjacent"变量赋值时出现问题
- enum是C++中的宏变量还是整数变量
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 将 Qvector<uint8_t> 转换为 QString
- 用C++中的一个变量定义一个常量
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 你能重载对象变量名本身返回的内容吗
- 内置函数可查看CPP中的成员变量
- 是否可以初始化不可复制类型的成员变量(或基类)
- 尝试通过多个向量访问变量时,向量下标超出范围
- 试图让变量检查数组中的某些内容
- 如果 (QString.contains()) 不能正常工作,请使用 temp bool 变量进行更正
- QString变量在使用QT Creator从键盘输入的双变量后跳过
- 如何以QString为成员变量初始化QXMLStreamWriter
- 将变量或QString传递到插槽(function())C 中的功能
- Qt4 C++:来自多个线程的QString变量使用崩溃
- 当我在方法中使用指针时,QString 变量更改为 QCharRef