'Segmentation fault when I access a regular array in QT C++

I get segment fault when I try to access an array in QT.

enter image description here

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