[SOLVED]QT 5.2.1 crash on QString::arg(QString const&, QString const&)
-
sometimes my application crashes, i'm using google breakpad as crash reporting system and this is the result of the dump:
@
...
8 MyApp!QString::arg(QString const&, QString const&) const [qstring.h : 796 + 0x2d]
eip = 0x080658c1 esp = 0xbfce0c70 ebp = 0xbfce0c98
Found by: stack scanning
9 MyApp!MainWindow::updateGrafica() [mainwindow.cpp : 1647 + 0x26]
eip = 0x080f0548 esp = 0xbfce0ca0 ebp = 0xbfce0e68 ebx = 0x082acff4
Found by: call frame info
10 MyApp!MainWindow::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) [moc_mainwindow.cpp : 295 + 0xb]
eip = 0x08164aae esp = 0xbfce0e70 ebp = 0xbfce0ea8 ebx = 0x082acff4
esi = 0x097d4b08
Found by: call frame info
....
@these are the source files:
mainwindow.cpp
mUtility.h
mUtility.cpp
plcCommunication.h
plcCommunication.cpp@
//FILE --> mainwindow.cpp
...
#include "mUtility.h"
#include "plcCommunication.h"
...MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);... if(plc.initConnection()){ qDebug() << "connected!!!"; QThread::msleep(1000); plc.start(QThread::HighestPriority); }else{ qDebug() << "not connected!!!"; } .... tGrafica = new QTimer(this); connect(tGrafica, SIGNAL(timeout()), this, SLOT(updateGrafica())); tGrafica->start(100); ...
}
void MainWindow::updateGrafica(){
...
for(int trs= 0; trs < 2; ++trs){
QLineEdit *l = this->findChild<QLineEdit *>(QString("txtTrs%1State").arg(trs));
l->setText(QString("%1 : %2").arg(QString::number(myUtility.stTrs[trs].iState), myUtility.stTrs[trs].sState)); //CRASH !!! -- LINE: 1647
}
...
}
FILE --> mUtility.h
#ifndef MUTILITY_H
#define MUTILITY_H
....
class mUtility : public QObject
{
Q_OBJECTpublic:
mUtility(QObject *parent = 0); ~mUtility(); struct trsGB{ ... int iState; QString sState; ... }; trsGB stTrs[2]; ...
};
extern mUtility myUtility;
#endif // MUTILITY_H
FILE --> mUtility.cpp
#include "mUtility.h"
...mUtility myUtility;
mUtility::mUtility(QObject *parent)
: QObject(parent)
{
Init();
}
FILE --> plcCommunication.h
#ifndef PLCCOMMUNICATION_H
#define PLCCOMMUNICATION_H#include <QThread>
...class PlcCommunication : public QThread
{
Q_OBJECT
public:PlcCommunication(QObject *parent = 0); ~PlcCommunication(); ...
};
extern PlcCommunication plc;
FILE --> plcCommunication.cpp
#include "plcCommunication.h"
#include "mUtility.h"
...PlcCommunication plc;
PlcCommunication::PlcCommunication(QObject *parent)
: QThread(parent)
{
....
}PlcCommunication::~PlcCommunication(){
}
bool PlcCommunication::initConnection(){
....
}void PlcCommunication::run(){
while(!bQuit){ .... myUtility.stTrs[0].iState = 300; myUtility.stTrs[0].sState = "state: 300"; .... myUtility.stTrs[1].iState = 550; myUtility.stTrs[1].sState = "state: 550"; .... }
}
@can anyone help me?
-
Try to use two arg() calls
@
l->setText(QString("%1 : %2")
.arg(myUtility.stTrs[trs].iState)
.arg(myUtility.stTrs[trs].sState));
@ -
QString QString::arg(const QString & a1, const QString & a2) const
This function overloads arg().
This is the same as str.arg(a1).arg(a2), except that the strings a1 and a2 are replaced in one pass. This can make a difference if a1 contains e.g. %1:
@QString str;
str = "%1 %2";str.arg("", "Hello"); // returns " Hello"
str.arg("").arg("Hello"); // returns "Hellof %2"@ -
Is it possible that updateGrafica() is called before
myUtility.stTrs[0] and myUtility.stTrs[1] are initialized? -
no it's not possible and the crashes are rare and random. could be a synchronization issue?
-
Yes it is possible that your timer slot and PlcCommunication have a race condition. Protect myUtility.stTrs and check if crashes will stop.
-
i have to use a QMutex or a QReadWriteLock or using volatile?
-
I would use QReadWriteLock.
volatile will not help here. -
i have to put a QReadWriteLock for every variable ?
-
I would create a QReadWriteLock variable in mUtility class then I would create a setter and a getter for myUtility.stTrs and use QReadLocker in the getter and QWriteLocker in the setter.
Then change your while loop to modify myUtility.stTrs through the setter and change MainWindow::updateGrafica() to retreive myUtility.stTrs through the getter.