如何解决QListWidget 删除 QListWidgetItem 导致分段错误
我有一个 C++ 应用程序,我正在读取 pcap
文件格式并处理 USB 数据包。对于每个数据包,我想创建一个 QListWidgetItem
,我将在其中存储一些数据,然后将其添加到 QListWidget
。这就是麻烦开始的地方。根据 QListWidget 文档,插入项目后:
列表小部件将获得该项目的所有权。
所以我认为它在 QListWidget
上删除所有 QListWidgetItems
。这些项目添加得很好,但是当我关闭我的应用程序时(我想那是在调用析构函数 od QListWidget
时,所以他正在调用每个 QListWidgetItem
的析构函数)我得到 delete_scalar exception
。根据调用堆栈,删除一些 QListWidgetItem 会触发它:
我的代码片段(这个函数会被 pcap 文件中的每个数据包调用,负责创建和添加项目):
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);
}
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;
}
}
}
}
}
编辑
我发现只有在通过 QListWidget
附加到 Itemmanager
类时才会发生此问题。在我的主要 Q_OBJECT 类 USB_Packet_Analyzer
(其中包含我要附加到的 QlistWidget
)中,我有插槽 on_OpenButton_clicked()
,如下所示:
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());
}
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();
}
现在,如果我在 on_OpenButton_clicked()
插槽中添加项目并关闭应用程序,则一切正常。但是当我创建 Itemmanager
实例并在该类中附加项目时,就会发生错误。难道我不允许将 QListWidget*
作为参数传递?
解决方法
您必须在循环中创建一个新项目。你不能重用指针,因为没有复制内容,只有指针存储在 QListWidget
,直到今天我还不能完全确定是什么导致了错误,但是在我修改了我正在使用的 USBPCAP
结构后它得到了修复。他们使用诸如 #pragma pack(1),#pragma pack(push)
之类的各种东西。看起来我遗漏了其中一些,这可能会导致在使用它们时出现一些未定义的行为。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。