c++qtqlistwidgetqlistwidgetitem

QListWidget deleting QListWidgetItem causes segmentaion fault


I have a C++ application where I am reading pcap file format and processing usb packets. For each packet, I would like to create a QListWidgetItem to which I am storing some data and then adding it to the QListWidget. Here is where the trouble begins. According to QListWidget documentation, after inserting item :

The list widget will take ownership of the item.

So what I thought is that its on QListWidget to delete all QListWidgetItems. The items are added fine, but when I close my app(I suppose thats when desctructor od QListWidget is called so he is calling desctructor of each QListWidgetItem) I get delete_scalar exception. According to call stack, deletion of some QListWidgetItem triggers it :call stack screen

Snippet of my code (this function is being called for each packet in pcap file and is responsible for creating and adding items):

 void ItemManager::ProcessPacket(QByteArray packetData)
    {
        const unsigned char* packet = (unsigned char*)packetData.data();
        PUSBPCAP_BUFFER_PACKET_HEADER usbh = (PUSBPCAP_BUFFER_PACKET_HEADER)packet;
    
        QListWidgetItem* item = new QListWidgetItem;
    
        //set USBPCAP header to item
        QByteArray usbhArray((const char*)packet, sizeof(USBPCAP_BUFFER_PACKET_HEADER));
        item->setData(dataHolder->USBPCAP_HEADER_DATA, QVariant(usbhArray));
        packet += sizeof(USBPCAP_BUFFER_PACKET_HEADER);
    
        if (usbh->transfer == USBPCAP_TRANSFER_ISOCHRONOUS || usbh->transfer == USBPCAP_TRANSFER_CONTROL) //check for optional header data
        {
            int additionalDataSize = usbh->headerLen - sizeof(USBPCAP_BUFFER_PACKET_HEADER);
            if (additionalDataSize > 0)
            {
                //set additional header data to item
                QByteArray additionalDataArray((const char*)(packet), additionalDataSize);
                item->setData(dataHolder->TRANSFER_OPTIONAL_HEADER, QVariant(additionalDataArray));
                packet += additionalDataSize;
            }
            else
            {
                item->setData(dataHolder->TRANSFER_OPTIONAL_HEADER, QVariant()); //QVariant creates invalid QVariant, later i just need to check with QVariant::isValid()
            }
        }
        else
        {
            item->setData(dataHolder->TRANSFER_OPTIONAL_HEADER, QVariant());
        }
    
        //set leftover data to item
        QByteArray leftoverDataArray((const char*)packet, usbh->dataLength);
        item->setData(dataHolder->TRANSFER_LEFTOVER_DATA, QVariant(leftoverDataArray));
    
        listWidget->insertItem(listWidget->count(), item);
    }

Calling of ProcessPacket function :

void ItemManager::ProcessFile(QString filename, bool liveReading)
{
    if (fileReader.OpenNewFile(filename))
    {
        if (fileReader.ReadFileHeader())
        {
            while (!stopButtonClicked)
            {
                while (!fileReader.EndOfFile())
                {
                    QByteArray packetData = fileReader.GetPacket();
                    if (!pauseButtonClicked)
                    {
                        ProcessPacket(packetData);
                    }
                }

                parent->Refresh();  //this is just calling QCoreApplication::processEvents();

                if (!atBottomOfList)
                {
                    listWidget->scrollToBottom();
                }

                if (liveReading)
                {
                    Sleep(50);
                }
                else
                {
                    return;
                }
            }
        }
    }
}

EDIT

I found out that this problem is happening only when appending to QListWidget through ItemManager class. In my main Q_OBJECT class USB_Packet_Analyzer(which holds QlistWidget that I am appending to) i have slot on_OpenButton_clicked() which looks like this :

void USB_Packet_Analyzer::on_OpenButton_clicked()
{
    QString fil = QFileDialog::getOpenFileName(this, "Select source file", ".", "Pcap files (*.pcap)");
    ItemManager manager(ui.listWidget,this);
    manager.ProcessFile(fil, ui.liveCaptureRadioButton->isChecked());
}

where in ItemManager class constructor looks like this :

ItemManager::ItemManager(QListWidget* listWidget, USB_Packet_Analyzer* parent)
{
    this->stopButtonClicked = false;
    this->pauseButtonClicked = false;
    this->atBottomOfList = false;
    this->listWidget = listWidget;
    this->parent = parent;
    this->dataHolder = DataHolder::GetDataHolder();
}

Now, if I add items in on_OpenButton_clicked() slot and close the app, everything is fine. But when I create ItemManager instance and append items in that class, the error occurs. Could it be that I am not allowed to pass QListWidget* as parameter ?


Solution

  • To this day I am not completely sure what caused the error, but it was fixed after I modified USBPCAP structs which I were using. They use all kind of stuff like #pragma pack(1) , #pragma pack(push) and so on. It looks like I was missing some of those, which might result in some undefined behaviour while using them.