gpt4 book ai didi

c++ - 由于在 Qt 中拖放导致未知的间歇性崩溃

转载 作者:太空宇宙 更新时间:2023-11-04 14:10:17 25 4
gpt4 key购买 nike

一天多来我一直在努力寻找这个错误,我开始发疯了......我已经重写并仔细检查了拖放代码,但无济于事。

它发生在主 Qt 事件循环 a.exec() 中,来自 valgrind 的堆栈跟踪如下所示。它有时会在 QMutex::Lock() 上崩溃(我只使用一个 QThread(主 qt 事件循环),所有其他线程都包含在后端并且是安全的)

由于我自己使用鼠标花了一个多小时才发现该错误,因此我编写了一个函数来移动鼠标,包括按下、释放、单击、双击。这会导致错误在大约十分钟内发生。

我会发布一些代码,但是它们有几千行用于拖放的东西(除了这个烦人的错误之外它工作得很好)

拖动可能发生在两种类型的项目中,并且两者基本相同。在鼠标移动事件中, drag->exec() 被调用。

我正在使用子类 mime 数据以允许它包含我需要的内容。

任何帮助都会很棒...

Invalid read of size 8
in main in Src/Program/main.cpp:77
Address 0x40 is not stack'd, malloc'd or (recently) free'd
1: QCoreApplication::postEvent(QObject*, QEvent*, int) in /usr/lib/x86_64-linux-gnu/libQtCore.so.4.8.1
2: /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.1
3: QApplication::x11ClientMessage(QWidget*, _XEvent*, bool) in /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.1
4: QApplication::x11ProcessEvent(_XEvent*) in /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.1
5: /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.1
6: g_main_context_dispatch in /lib/x86_64-linux-gnu/libglib-2.0.so.0.3200.3
7: /lib/x86_64-linux-gnu/libglib-2.0.so.0.3200.3
8: g_main_context_iteration in /lib/x86_64-linux-gnu/libglib-2.0.so.0.3200.3
9: QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) in /usr/lib/x86_64-linux-gnu/libQtCore.so.4.8.1
10: /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.1
11: QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) in /usr/lib/x86_64-linux-gnu/libQtCore.so.4.8.1
12: QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) in /usr/lib/x86_64-linux-gnu/libQtCore.so.4.8.1
13: QCoreApplication::exec() in /usr/lib/x86_64-linux-gnu/libQtCore.so.4.8.1
14: main in

主要内容:

  QApplication a(argc, argv);

if (testing)
{
UnitTest::RunAllTests();
return 0;
}

MainWindow w(debug, testing);
w.show();
w.InitialiseGUI();
return a.exec(); <- line 77

创建拖动对象时:

void ElementItem::mouseMoveEvent(QMouseEvent * event)
{
if
(
(event->buttons() & Qt::LeftButton) &&
((event->pos() - _drag_start_position).manhattanLength() > DRAG_START_DISTANCE)
)
{

_control_and_status->_drag_control_object->NotifyDragStarted();

try
{

// Ensure that if something goes wrong and old widget does not get deleted.
// create a new drag object
_drag = new QDrag(this);

// create a custom mime type (subclass of QMimeType)
WidgetMimeType *mimeData = new WidgetMimeType;

ChainWidgetBase * base_widget = LoadElementAndWidget();

// Set the widget as this object
if (base_widget)
{
mimeData->_widget = (QWidget *) base_widget;
mimeData->_delete_on_failure = true;
mimeData->_widget_deletion_required = &_widget_deletion_required;
}
else
{
delete _drag;
_drag = NULL;
throw GeneralException(ErrorReporting::ERROR_IN_DROPPABLE_CONTAINER, "Null widget");
}

_drag->setMimeData(mimeData);

Qt::DropAction dropAction = _drag->exec();

}
catch(...)
{
}

DragStopped();
}
}

这是创建拖动对象的地方之一,还有 3 个做不同的事情,但使用相同的方法

子类 mime 数据:

#pragma once
#include <QtGui>

class WidgetMimeType : public QMimeData
{
public:
WidgetMimeType():
_widget(NULL),
_delete_on_failure(false),
_deletion_required_dummy(false),
_widget_deletion_required(&_deletion_required_dummy)
{
}

~WidgetMimeType()
{
}

QWidget * _widget;
bool _delete_on_failure;
bool _deletion_required_dummy;
bool * _widget_deletion_required;
};

编辑:我已经添加了 QT 源,崩溃的位置:

void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
{
if (receiver == 0) {
qWarning("QCoreApplication::postEvent: Unexpected null receiver");
delete event;
return;
}

QThreadData * volatile * pdata = &receiver->d_func()->threadData;
QThreadData *data = *pdata; <--- CRASHES HERE
if (!data) {
// posting during destruction? just delete the event to prevent a leak
delete event;
return;
}

// lock the post event mutex
data->postEventList.mutex.lock();

// if object has moved to another thread, follow it
while (data != *pdata) {
data->postEventList.mutex.unlock();

data = *pdata;
if (!data) {
// posting during destruction? just delete the event to prevent a leak
delete event;
return;
}

data->postEventList.mutex.lock();
}

崩溃发生在上面显示的行中,上面写着<---- CRASH HERE。它来自取消引用指针。这些信息是否足以确定发生了什么?

最佳答案

Qt::DropAction dropAction = _drag->exec(); 这是您的代码可能会崩溃的行。我没有完全阅读您的代码,但我假设在拖动小部件后您正在使用 deleteLater() 函数删除原始小部件。如果是这种情况,那么对于窗口平台 tit 将正常工作,因为 _drag->exec() 将阻止事件,如果是 mac 或 Linux,它将不会阻止事件。这样, _drag->exec() 的事件在执行事件时得到空指针。

我知道这个 deleteLater() 在控制返回到事件循环时对象将被删除时执行。

一般来说,deleteLater()是在_drag->exec()完成之前执行的。

关于c++ - 由于在 Qt 中拖放导致未知的间歇性崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14856836/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com