'Segmentation fault when I access a regular array in QT C++
I get segment fault when I try to access an array in QT.
The code is very simple.
I have a class, were I have a private array declared.
uint16_t analogSingleInput[12] = {0};
When I try to access the array.
uint16_t MessageServiceThread::getAnalogSingleInput(int index){
qDebug() << "index:" + QString::number(index);
qDebug() << "hello!";
qDebug() << "size: = " + QString::number(sizeof(analogSingleInput));
qDebug() << "analogSingleInput[index]: " + QString::number(this->analogSingleInput[0]);
return analogSingleInput[index];
}
I get this output:
"index:0"
hello!
"size: = 24"
That means that the C++ program crashes here:
qDebug() << "analogSingleInput[index]: " + QString::number(this->analogSingleInput[0]);
So my question is simple:
Can I delcare an array like this in QT C++ ? See the uint16_t arrays.
Have I initilize the array correctly?
#ifndef MESSAGESERVICETHREAD_H
#define MESSAGESERVICETHREAD_H
#include <QObject>
#include <QThread>
#include "../../tools/opensaej1939/Open_SAE_J1939/Open_SAE_J1939.h"
#define MAX_ADC 12
#define MAX_DADC 5
#define MAX_ENCODER 2
#define MAX_INPUT_CAPTURE 2
#define MAX_DIGITAL_INPUT 9
#define MAX_PWM 8
#define MAX_DAC 3
#define MAX_AUXILIARY_VALVE_COMMAND_STANDARD_FLOW 16
class MessageServiceThread : public QThread
{
Q_OBJECT
public:
MessageServiceThread(J1939 *j1939 = nullptr);
void run();
uint8_t getAnalogGain(int index);
uint16_t getPWMPrescaler(int index);
bool getDigitalInput(int index);
uint16_t getAnalogSingleInput(int index);
uint16_t getAnalogDifferentialInput(int index);
uint16_t getInputCapture(int index);
uint16_t getEncoderInput(int index);
uint16_t getPWM(int index);
uint16_t getAnalogSingleOutput(int index);
signals:
int signalTransmitUSBData(QByteArray usbDataRaw);
public slots:
void slotSetControlSignals(uint16_t PWM[], uint16_t analogSingleOutput[]);
void slotReadUSBData(QByteArray usbDataRaw);
void slotSetMessageServiceThreadActive(bool active);
void slotSetGeneralValveCommandExtendedFlow(int32_t generalValveCommandExtendedFlow);
void slotSetAuxiliaryValveCommandStandardFlow(int16_t axuiliaryValveCommandStandardFlow[]);
private:
/* Settings fields */
uint8_t analogGain[3] = {0};
uint16_t pwmPrescaler[2] = {0};
/* Measurement fields */
bool digitalInput[MAX_DIGITAL_INPUT] = {false};
uint16_t analogSingleInput[MAX_ADC] = {0};
uint16_t analogDifferentialInput[MAX_DADC] = {0};
uint16_t inputCapture[MAX_INPUT_CAPTURE] = {0};
uint16_t encoderInput[MAX_ENCODER] = {0};
uint16_t PWM[MAX_PWM] = {0};
uint16_t analogSingleOutput[MAX_DAC] = {0};
int32_t generalValveCommandExtendedFlow;
uint16_t auxiliaryValveCommandStandardFlow[MAX_AUXILIARY_VALVE_COMMAND_STANDARD_FLOW] = {0};
/* Active fields */
bool messageServiceThreadActive;
/* Other structs */
J1939 *j1939;
/* Other functions */
void sendCanMessageSAEJ1939ToSTM32PLC();
void sendControlSignalsToSTM32PLC();
uint32_t readAnalogGainFromSTM32PLC(QByteArray usbDataRaw, uint32_t byteIndex);
uint32_t readPWMPrescalersFromSTM32PLC(QByteArray usbDataRaw, uint32_t byteIndex);
uint32_t readMeasurementsFromSTM32PLC(QByteArray usbDataRaw, uint32_t byteIndex);
uint32_t readCANBusMessageFromSTM32PLC(QByteArray usbDataRaw, uint32_t byteIndex);
};
#endif // MESSAGESERVICETHREAD_H
The whole code:
#include "messageservicethread.h"
#include "code/tools/opensaej1939/Open_SAE_J1939/Open_SAE_J1939.h"
#include <QDebug>
/* For the CAN read callback function */
static uint8_t canMessageSAEJ1939[15] = {0};
static uint8_t CAN_IDE;
static uint32_t CAN_ID;
static uint8_t CAN_DATA[8] = {0};
static uint8_t CAN_DLC;
/* Message types for STM32 PLC */
typedef enum{
READ_CAN_BUS_MESSAGE_TYPE,
READ_CONTROL_SIGNAL_MESSAGE_TYPE,
READ_PWM_PRESCALAR_MESSAGE_TYPE,
READ_ANALOG_INPUT_GAIN_MESSAGE_TYPE,
SEND_BACK_ANALOG_GAIN_MESSAGE_TYPE,
SEND_BACK_PWM_PRESCALER_MESSAGE_TYPE,
SEND_BACK_MEASUREMENT_MESSAGE_TYPE,
SEND_BACK_CAN_BUS_MESSAGE_TYPE,
SEND_BACK_FEEDBACK_BYTE_MESSAGE_TYPE
}MESSAGE_TYPES;
#define CAN_ID_STD (0x00000000U) /*!< Standard Id */
#define CAN_ID_EXT (0x00000004U) /*!< Extended Id */
/* SAE J1939 callback function for sending a message */
void Callback_Function_Send(uint32_t ID, uint8_t DLC, uint8_t data[]){
canMessageSAEJ1939[0] = READ_CAN_BUS_MESSAGE_TYPE;
canMessageSAEJ1939[1] = CAN_ID_EXT;
canMessageSAEJ1939[2] = ID >> 24;
canMessageSAEJ1939[3] = ID >> 16;
canMessageSAEJ1939[4] = ID >> 8;
canMessageSAEJ1939[5] = ID;
canMessageSAEJ1939[6] = DLC;
for(uint8_t i = 0; i < 8; i++)
canMessageSAEJ1939[7+i] = data[i];
};
/* SAE J1939 callback function for reading a message */
void Callback_Function_Read(uint32_t *ID, uint8_t data[], bool *is_new_message){
/* Check if it's a message for SAE J1939 */
if(CAN_IDE == CAN_ID_STD){
*is_new_message = false;
}else{
*ID = CAN_ID;
memcpy(data, CAN_DATA, 8);
*is_new_message = true;
}
};
MessageServiceThread::MessageServiceThread(J1939 *j1939) : j1939(j1939)
{
CAN_Set_Callback_Functions(Callback_Function_Send, Callback_Function_Read);
}
void MessageServiceThread::run(){
int i = 0;
while(true){
/* A wait statement */
while(!messageServiceThreadActive){
msleep(1000);
}
/* Send CAN message with a 100 ms intervall */
if(i >= 100){
sendCanMessageSAEJ1939ToSTM32PLC();
i = 0;
}else{
i++;
}
/* Send PWM and analog signal output */
sendControlSignalsToSTM32PLC();
/* Sleep 1 ms */
msleep(1);
}
}
void MessageServiceThread::slotSetControlSignals(uint16_t PWM[], uint16_t analogSingleOutput[]){
memcpy(this->PWM, PWM, sizeof(this->PWM));
memcpy(this->analogSingleOutput, analogSingleOutput, sizeof(this->analogSingleOutput));
}
void MessageServiceThread::slotReadUSBData(QByteArray usbDataRaw){
/* Check what type of data */
uint32_t byteIndex = 0;
uint32_t usbDataLength = usbDataRaw.length();
while(byteIndex < usbDataLength){
uint8_t messageType = usbDataRaw.at(byteIndex++);
switch(messageType){
case SEND_BACK_ANALOG_GAIN_MESSAGE_TYPE:
byteIndex = readAnalogGainFromSTM32PLC(usbDataRaw, byteIndex);
break;
case SEND_BACK_PWM_PRESCALER_MESSAGE_TYPE:
byteIndex = readPWMPrescalersFromSTM32PLC(usbDataRaw, byteIndex);
break;
case SEND_BACK_MEASUREMENT_MESSAGE_TYPE:
byteIndex = readMeasurementsFromSTM32PLC(usbDataRaw, byteIndex);
break;
case SEND_BACK_CAN_BUS_MESSAGE_TYPE:
byteIndex = readCANBusMessageFromSTM32PLC(usbDataRaw, byteIndex);
Open_SAE_J1939_Listen_For_Messages(j1939); /* This listener will only be called once we got new CAN data */
/* TODO: Read the CANopen message her as well */
break;
}
}
}
void MessageServiceThread::slotSetMessageServiceThreadActive(bool active){
messageServiceThreadActive = active;
}
uint32_t MessageServiceThread::readAnalogGainFromSTM32PLC(QByteArray usbDataRaw, uint32_t byteIndex){
analogGain[0] = usbDataRaw.at(byteIndex++);
analogGain[1] = usbDataRaw.at(byteIndex++);
analogGain[2] = usbDataRaw.at(byteIndex++);
return byteIndex;
}
uint32_t MessageServiceThread::readPWMPrescalersFromSTM32PLC(QByteArray usbDataRaw, uint32_t byteIndex){
pwmPrescaler[0] = usbDataRaw.at(byteIndex++);
pwmPrescaler[1] = usbDataRaw.at(byteIndex++);
return byteIndex;
}
uint32_t MessageServiceThread::readMeasurementsFromSTM32PLC(QByteArray usbDataRaw, uint32_t byteIndex){
/* Digital inputs */
for(int i = 0; i < MAX_DIGITAL_INPUT; i++)
digitalInput[i] = usbDataRaw.at(byteIndex++);
/* Analog single inputs */
for(int i = 0; i < MAX_ADC; i++){
analogSingleInput[i] = (usbDataRaw.at(byteIndex) << 8) | usbDataRaw.at(byteIndex + 1);
byteIndex += 2;
}
/* Analog differential inputs */
for(int i = 0; i < MAX_DADC; i++){
analogDifferentialInput[i] = (usbDataRaw.at(byteIndex) << 8) | usbDataRaw.at(byteIndex + 1);
byteIndex += 2;
}
/* Inputs capture */
for(int i = 0; i < MAX_INPUT_CAPTURE; i++){
inputCapture[i] = (usbDataRaw.at(byteIndex) << 8) | usbDataRaw.at(byteIndex + 1);
byteIndex += 2;
}
/* Encoder inputs */
for(int i = 0; i < MAX_ENCODER; i++){
encoderInput[i] = (usbDataRaw.at(byteIndex) << 8) | usbDataRaw.at(byteIndex + 1);
byteIndex += 2;
}
return byteIndex;
}
uint32_t MessageServiceThread::readCANBusMessageFromSTM32PLC(QByteArray usbDataRaw, uint32_t byteIndex){
CAN_IDE = usbDataRaw.at(byteIndex++);
CAN_ID = (usbDataRaw.at(byteIndex) << 24) | (usbDataRaw.at(byteIndex + 1) << 16) | (usbDataRaw.at(byteIndex + 2) << 8) | usbDataRaw.at(byteIndex + 3);
byteIndex += 4;
CAN_DLC = usbDataRaw.at(byteIndex++);
for(int i = 0; i < 8; i++)
CAN_DATA[i] = usbDataRaw.at(byteIndex++);
return byteIndex;
}
void MessageServiceThread::sendCanMessageSAEJ1939ToSTM32PLC(){
/* Get the length of the data */
uint8_t DLC = canMessageSAEJ1939[6];
/* Check if the data is longer than 0 - A SAE J1939 message always holds data */
if(DLC > 0){
QByteArray usbDataRaw;
int canMessageSize = sizeof(canMessageSAEJ1939);
for(int i = 0; i < canMessageSize; i++){
usbDataRaw.append(canMessageSAEJ1939[i]);
canMessageSAEJ1939[i] = 0; /* Clear */
}
emit signalTransmitUSBData(usbDataRaw);
}
}
void MessageServiceThread::sendControlSignalsToSTM32PLC(){
QByteArray usbDataRaw;
usbDataRaw.append(READ_CONTROL_SIGNAL_MESSAGE_TYPE);
int pwmSize = sizeof(PWM);
for(int i = 0; i < pwmSize; i++){
usbDataRaw.append(PWM[i + i] >> 8);
usbDataRaw.append(PWM[i + i + 1]);
}
int analogSingleOutputSize = sizeof(analogSingleOutput);
for(int i = 0; i < analogSingleOutputSize; i++){
usbDataRaw.append(analogSingleOutput[i + i] >> 8);
usbDataRaw.append(analogSingleOutput[i + i + 1]);
}
emit signalTransmitUSBData(usbDataRaw);
}
uint8_t MessageServiceThread::getAnalogGain(int index){
return analogGain[index];
}
uint16_t MessageServiceThread::getPWMPrescaler(int index){
return pwmPrescaler[index];
}
bool MessageServiceThread::getDigitalInput(int index){
return digitalInput[index];
}
uint16_t MessageServiceThread::getAnalogSingleInput(int index){
qDebug() << "index:" + QString::number(index);
qDebug() << "hello!";
qDebug() << "size: = " + QString::number(sizeof(analogSingleInput));
qDebug() << "analogSingleInput[index]: " + QString::number(this->analogSingleInput[0]);
return analogSingleInput[index];
}
uint16_t MessageServiceThread::getAnalogDifferentialInput(int index){
return analogDifferentialInput[index];
}
uint16_t MessageServiceThread::getInputCapture(int index){
return inputCapture[index];
}
uint16_t MessageServiceThread::getEncoderInput(int index){
return encoderInput[index];
}
uint16_t MessageServiceThread::getPWM(int index){
return PWM[index];
}
uint16_t MessageServiceThread::getAnalogSingleOutput(int index){
return analogSingleOutput[index];
}
void MessageServiceThread::slotSetGeneralValveCommandExtendedFlow(int32_t generalValveCommandExtendedFlow){
this->generalValveCommandExtendedFlow = generalValveCommandExtendedFlow;
}
void MessageServiceThread::slotSetAuxiliaryValveCommandStandardFlow(int16_t auxiliaryValveCommandStandardFlow[]){
memcpy(this->auxiliaryValveCommandStandardFlow, auxiliaryValveCommandStandardFlow, sizeof(this->auxiliaryValveCommandStandardFlow));
}
This code calls the function. Look at getCellValue(int column, QString columnName, QVariant cellValue, int *dataTypeID).
The cellForm object as an QMap where I store the object.
#include "databasemeasurementtemplatewindow.h"
#include "ui_databasemeasurementtemplatewindow.h"
#include "databasemeasurementtype/databasemeasurementtypewindow.h"
DatabaseMeasurementTemplateWindow::DatabaseMeasurementTemplateWindow(QWidget *parent) :
QWidget(parent),
ui(new Ui::DatabaseMeasurementTemplateWindow)
{
ui->setupUi(this);
}
DatabaseMeasurementTemplateWindow::~DatabaseMeasurementTemplateWindow()
{
delete ui;
}
void DatabaseMeasurementTemplateWindow::on_addRowPushButton_clicked()
{
ui->templateTableWidget->setRowCount(++rows);
for(int i = 0; i < columns; i++){
/* Create a button for the cell */
QPushButton* cellButton = new QPushButton("Empty");
/* Create a new window */
DatabaseMeasurementTypeWindow* cellForm = new DatabaseMeasurementTypeWindow(nullptr, cellButton);
/* Set the cellForm */
cellForms[QString::number(rows-1) + "x" + QString::number(i)] = cellForm;
/* Set the button event */
connect(cellButton, &QPushButton::clicked, [=]() {cellForm->show();});
/* AAdd to the table widget */
ui->templateTableWidget->setCellWidget(rows-1, i, cellButton);
}
}
void DatabaseMeasurementTemplateWindow::on_appendColumnPushButton_clicked()
{
ui->templateTableWidget->setColumnCount(++columns);
for(int i = 0; i < rows; i++){
/* Create a button for the cell */
QPushButton* cellButton = new QPushButton("Empty");
/* Create a new window */
DatabaseMeasurementTypeWindow* cellForm = new DatabaseMeasurementTypeWindow(nullptr, cellButton);
/* Set the cellForm */
cellForms[QString::number(i) + "x" + QString::number(columns - 1)] = cellForm;
/* Set the button event */
connect(cellButton, &QPushButton::clicked, [=]() {cellForm->show();});
/* AAdd to the table widget */
ui->templateTableWidget->setCellWidget(i, columns-1, cellButton);
}
}
void DatabaseMeasurementTemplateWindow::on_removeColumnPushButton_clicked()
{
QModelIndexList selectedColumn = ui->templateTableWidget->selectionModel()->selectedColumns();
for(int i = 0; i < selectedColumn.length(); i++){
int column = selectedColumn.at(i).column();
ui->templateTableWidget->removeColumn(column);
for(int i = 0; i < rows; i++)
cellForms.remove(QString::number(i) + "x" + QString::number(columns - 1));
columns--;
}
/* Delete all when there are no columns */
if(ui->templateTableWidget->columnCount() == 0){
ui->templateTableWidget->setColumnCount(0);
ui->templateTableWidget->setRowCount(0);
rows = columns = 0;
}
}
void DatabaseMeasurementTemplateWindow::on_deleteRowPushButton_clicked()
{
QModelIndexList selectedRows = ui->templateTableWidget->selectionModel()->selectedRows();
for(int i = 0; i < selectedRows.length(); i++){
int row = selectedRows.at(i).row();
ui->templateTableWidget->removeRow(row);
for(int i = 0; i < columns; i++)
cellForms.remove(QString::number(rows-1) + "x" + QString::number(i));
rows--;
}
/* Delete all when there are no rows */
if(ui->templateTableWidget->rowCount() == 0){
ui->templateTableWidget->setColumnCount(0);
ui->templateTableWidget->setRowCount(0);
rows = columns = 0;
}
}
void DatabaseMeasurementTemplateWindow::updateCellValues(){
/* Get selected rows */
int row = ui->templateTableWidget->selectionModel()->selectedRows().at(0).row();
qDebug() << "Row:" + QString::number(row);
int columnCount = ui->templateTableWidget->columnCount();
for(int j = 0; j < columnCount; j++){
cellForms[QString::number(row) + "x" + QString::number(j)]->updateCellValue();
}
}
int DatabaseMeasurementTemplateWindow::getColumnCount(){
return ui->templateTableWidget->columnCount();
}
void DatabaseMeasurementTemplateWindow::getCellValue(int column, QString columnName, QVariant cellValue, int *dataTypeID){
qDebug() << "Column:" + QString::number(column);
int row = ui->templateTableWidget->selectionModel()->selectedRows().at(0).row();
qDebug() << "Row:" + QString::number(row);
cellForms[QString::number(row) + "x" + QString::number(column)]->getCellValue(columnName, cellValue, dataTypeID);
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|

