Solved App Crash C++ Runtime Library
-
I'm running this small app to read some sensors throughout an Arduino board, the problem is if i move too much the window around and play with it i get a C++ Runtime Library crash either using common Qt widgets or Qwt widgets as follows:
Microsoft Visual C++ Runtime Library
This application has requested the runtime to terminate it in a unsual way.
Please contact the application's support team for more information.
Plus it gets a little bit laggy when i open the port and start reading from the board, Why is that?
This are my files:
.proQT += core gui serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = EMS-ver2TEST TEMPLATE = app SOURCES += \ main.cpp \ puertoserie2.cpp \ widget.cpp HEADERS += \ puertoserie2.h \ widget.h QMAKE_CXXFLAGS += -std=gnu++14
Headers:
puertoserie2.h#ifndef PUERTOSERIE2_H #define PUERTOSERIE2_H #include <QObject> #include <QWidget> #include <QSerialPort> #include <QByteArray> #include <QVector> #include <QPushButton> class PuertoSerie2 : public QWidget{ Q_OBJECT public: explicit PuertoSerie2(QWidget *parent = nullptr); private Q_SLOTS: // Conecta con el dispositivo transmisor void conexion(); // Lleva a cabo una lectura del vector de informacion entrante void leerPlaca(); Q_SIGNALS: void SENSOR_A(int); void SENSOR_B(int); void SENSOR_C(int); void SENSOR_D(int); private: void emiteValor(); char banderaEstado(QByteRef); void estado(char, char); void setValorSensores(); int refactorizar(QByteArray); // Estado del boton int mPuertoEstado; // Numero del sensor a leer o modificar int mComa; QSerialPort *mPlaca; // Informacion de los sensores en arreglos para un manejo mas compacto QVector<QByteArray> mSensorList; QVector <int> mSensorValor; // Buffer de entrada QByteArray mBuffer; // Puerto de la PC QString mPuerto; // Boton que establece la conexion QPushButton *mBoton; }; #endif // PUERTOSERIE2_H
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QDial> class Widget : public QWidget{ Q_OBJECT public: Widget(QWidget *parent = 0); ~Widget(); private: QWidget *crearDial(QDial *); }; #endif // WIDGET_H
Sources:
puertoserie2.cpp#include "puertoserie2.h" #include <QMessageBox> #include <QBoxLayout> #include <QDebug> PuertoSerie2::PuertoSerie2(QWidget *parent) : QWidget(parent){ mComa = 0; mPuertoEstado = 0; mPuerto = "COM3"; mBuffer = ""; mSensorList.push_back(QByteArray()); qDebug() << "Vector de QByteArray" << mSensorList.at(0); mSensorValor.push_back(0); qDebug() << "Vector de double" << mSensorValor.at(0); mBoton = new QPushButton("Abrir Puerto", this); QHBoxLayout *layout = new QHBoxLayout(this); layout->addWidget(mBoton); layout->addStretch(); connect(mBoton, SIGNAL(clicked()), this, SLOT(conexion())); } char PuertoSerie2::banderaEstado(QByteRef buffer){ // 'a' = 42 (asterisco, inicio de cadena) // 'b' = 44 (coma, separador) // 'c' >= 48 (informacion, contenido) int var = (int)buffer; if(var == 42){ return 'a'; } else if(var == 44){ return 'b'; } else if(var >= 48){ return 'c'; } return 'd'; } void PuertoSerie2::estado(char bandera, char byte){ switch (bandera) { // El estado a se supone que limpia los valores enteriores del vector // para introducir las nuevas lecturas case 'a': qDebug() << "\n----------Caso 'a' disparado: " << byte; qDebug() << "\nTam de los vectores: " << mSensorList.size() << "| " << mSensorValor.size(); qDebug() << "\nTam de coma: " << mComa; for(int i = 0; i < mSensorValor.size(); ++i){ mSensorValor[i] = 0.0; } for(int i = 0; i < mSensorList.size(); ++i){ mSensorList[i].clear(); } mComa = 0; break; // El estado es un separador, aumenta el lugar del vector case 'b': qDebug() << "\n----------Caso 'b' disparado: " << byte; qDebug() << "\nTam de los vectores: " << mSensorList.size() << "| " << mSensorValor.size(); qDebug() << "\nTam de coma: " << mComa; emiteValor(); mSensorValor.push_back(0); mSensorList.push_back(QByteArray()); ++mComa; qDebug() << "\nAcciones llevadas a cabo"; qDebug() << "\nTam de los vectores: " << mSensorList.size() << "| " << mSensorValor.size(); qDebug() << "\nTam de coma: " << mComa; break; // Tenemos informacion y la signamos al posicion actual de la coma case 'c': qDebug() << "\n----------Caso 'c' disparado: " << byte; qDebug() << "Coma actual: " << mComa; qDebug() << "\nTam de los vectores: " << mSensorList.size() << "| " << mSensorValor.size(); mSensorList[mComa] += byte; break; default: qDebug() << "\n%%%%%%%%%%Final de la Cadena"; qDebug() << "\nTam de los vectores: " << mSensorList.size() << "| " << mSensorValor.size(); emiteValor(); mBuffer.clear(); while(mSensorList.size() > 1){ mSensorList.pop_back(); } while(mSensorValor.size() > 1){ mSensorValor.pop_back(); } break; } } void PuertoSerie2::conexion(){ if (mPuertoEstado == 0){ mPlaca = new QSerialPort(this); mPlaca->setPortName(mPuerto); mPlaca->open(QIODevice::ReadWrite); if(mPlaca->isOpen() == false){ QMessageBox::information(this, "Estado", "Error al Abrir el puerto: " + mPuerto); } else { mPlaca->setBaudRate(QSerialPort::Baud9600); mPlaca->setStopBits(QSerialPort::OneStop); mPlaca->setParity(QSerialPort::NoParity); mPlaca->setDataBits(QSerialPort::Data8); mPlaca->setFlowControl(QSerialPort::NoFlowControl); connect(mPlaca, SIGNAL(readyRead()), this, SLOT(leerPlaca())); mBoton->setText("Cerrar Puerto"); QMessageBox::information(this, "Estado", "Puerto: " + mPuerto + " Abierto"); mPuertoEstado = 1; } } else if (mPuertoEstado == 1){ mPlaca->close(); mPlaca->destroyed(); mPuertoEstado = 0; mBoton->setText("Abrir Puerto"); QMessageBox::information(this, "Estado", "Puerto: " + mPuerto + " Cerrado"); } } void PuertoSerie2::leerPlaca(){ mBuffer = mPlaca->readAll(); qDebug() << "\n>>>>>>>> Informacion de entrada: " << mBuffer; for(int i = 0; i < mBuffer.size(); ++i){ estado(banderaEstado(mBuffer[i]), mBuffer.at(i)); } } int PuertoSerie2::refactorizar(QByteArray byte){ // Convierte el valor de binario a un doble usable // qDebug() << "\nRefactorizando: " << byte; QString cadena = byte; int i = cadena.toInt(); // qDebug() << "\nRefactorizado: " << i; return i; } void PuertoSerie2::setValorSensores(){ qDebug() << "\nSeteando Valores..."; for(int i = 0; i < mSensorValor.size(); ++i){ mSensorValor[i] = refactorizar(mSensorList.at(i)); } } void PuertoSerie2::emiteValor(){ setValorSensores(); qDebug() <<"\nValores: " << mSensorValor.at(mComa); switch(mComa){ case 0: emit SENSOR_A(mSensorValor.at(mComa)); break; case 1: emit SENSOR_B(mSensorValor.at(mComa)); break; case 2: emit SENSOR_C(mSensorValor.at(mComa)); break; case 3: emit SENSOR_D(mSensorValor.at(mComa)); break; } }
widget.cpp
#include "widget.h" #include "puertoserie2.h" #include <QDial> #include <QBoxLayout> #include <QLabel> #include <QFont> Widget::Widget(QWidget *parent) : QWidget(parent){ PuertoSerie2 *port = new PuertoSerie2; QDial *dial = new QDial; connect(port, SIGNAL(SENSOR_A(int)), dial, SLOT(setValue(int))); QWidget *dialWidget = crearDial(dial); QDial *dialA = new QDial; connect(port, SIGNAL(SENSOR_B(int)), dialA, SLOT(setValue(int))); QWidget *dialAWidget = crearDial(dialA); QDial *dialB = new QDial; connect(port, SIGNAL(SENSOR_C(int)), dialB, SLOT(setValue(int))); QWidget *dialBWidget = crearDial(dialB); QDial *dialC = new QDial; connect(port, SIGNAL(SENSOR_D(int)), dialC, SLOT(setValue(int))); QWidget *dialCWidget = crearDial(dialC); QHBoxLayout *mainLayout = new QHBoxLayout(this); mainLayout->addWidget(dialWidget); mainLayout->addWidget(dialAWidget); mainLayout->addWidget(dialBWidget); mainLayout->addWidget(dialCWidget); mainLayout->addWidget(port); this->setLayout(mainLayout); } Widget::~Widget(){ } QWidget *Widget::crearDial(QDial* dial){ int min = 0; int max = 100; dial->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); dial->setMinimum(min); dial->setMaximum(max); QFont font; font.setBold(true); QLabel *label = new QLabel; label->setAlignment(Qt::AlignHCenter); label->setFont(font); connect(dial, SIGNAL(valueChanged(int)), label, SLOT(setNum(int))); label->setNum(dial->value()); QVBoxLayout *dialLayout = new QVBoxLayout; dialLayout->addWidget(dial); dialLayout->addWidget(label); QWidget *box = new QWidget; box->setLayout(dialLayout); return box; }
main.cpp
#include "widget.h" #include <QApplication> int main(int argc, char *argv[]){ QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
-
Hi @onimusha,
There's a few suspicious things that could be causing your problems. Let's start with a couple of the ones that stand out to me.
It seems that PuertoSerie2::leerPlaca is not checking the validity of the PuertoSerie2::mPlaca member before dereferencing it. I can see that your code logic would normally never expect it to be called without being initialised first, but as its connected to a signal, you can't guarantee the order of the events that destroy and use mPlaca (a quick validity check is always advisable anyway).
Also, the way PuertoSerie2::conexion destroys mPlaca looks risky to me... specifically, the
mPlaca->destroyed();
call is (probably) bad - QObject::destroyed is a signal, and probably should not be called this way (at best, it will be ignored, at worst, it will put the object in a very unintended state).A better approach might be something like:
void PuertoSerie2::conexion(){ ... mPlaca->close(); mPlaca->deleteLater(); mPlaca = nullptr; ... }
Then in PuertoSerie2::leerPlaca, check if mPlace is null or not (and/or disconnect the slot prior to the deleteLater call above). As the code stands currently, leerPlace could be calling readAll on a QSerialPort object on which you have invoked QObject::destroyed (which may well have corrupted the object).
So try fixing up the management of your PuertoSerie2::mPlace pointer's lifecycle, and see if that helps.
Cheers.
-
Hi @Paul-Colby,
Changing a few lines:else if (mPuertoEstado == 1){ mPlaca->close(); mPlaca->deleteLater(); mPlaca = nullptr; mPuertoEstado = 0; mBoton->setText("Abrir Puerto"); QMessageBox::information(this, "Estado", "Puerto: " + mPuerto + " Cerrado"); }
and:
if(mPlaca != nullptr){ mBuffer = mPlaca->readAll(); qDebug() << "\n>>>>>>>> Informacion de entrada: " << mBuffer; for(int i = 0; i < mBuffer.size(); ++i){ estado(banderaEstado(mBuffer[i]), mBuffer.at(i)); } }
as you said makes thinks even worse. the whole thing crashes in 2 sec, i cannot think how to manage that king of menber life cicle because this reaches my level of understanding about C++ / Qt / System platform
-
@Paul-Colby
One thing to notice is that the same code runs smoother on my IBM thinkpad Z60t under Lubuntu 14.04. Just wonder why.... -
You should run a debug build through the debugger to see where it crashes
-
Hello @jsulm i did that alrdy and nothing pops up when the crash happens
-
@jsulm I just want to know if there is something wrong in my code that could cause the crash besides my fuzzy logic to write code and algorithms. Other than that i think its my windows 7 machine.
-
I think the problem lies in windows asynchronous tasks...... not being able to read the buffer properly while taking care of other tasks like repainting the window i'm currently moving, as a result my QVector goes out of index.