我一直试图找到这个错误超过一天了,我开始疯了......我已经重新编写并仔细检查拖放代码无效。
它出现在主Qt事件循环a.exec()中,其中包含来自valgrind的堆栈跟踪,如下所示。它有时会在QMutex :: Lock()上崩溃(我只使用一个QThread(主qt事件循环),所有其他线程都包含在后端并且是安全的)
由于虫子花了一个多小时自己出现鼠标,我写了一个功能,可以让鼠标按下,释放,点击,双击。这导致错误在大约十分钟内发生。
我会发布一些代码,但是拖放的东西是几千行(除了这个烦人的bug之外,它完美地工作)
拖动可以在两种类型的项目中发生,并且两者基本相同。在鼠标移动事件中,调用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个做不同的事情,但使用相同的方法
亚模糊哑剧数据:
#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();
}
崩溃发生在上面显示的行上,其中显示&lt; ---- CRASH HERE。它取决于引用指针。这是否足以确定发生了什么?
答案 0 :(得分:0)
Qt::DropAction dropAction = _drag->exec();
,这是您的代码可能会崩溃的行。我没有完全阅读您的代码,但是我假设拖动小部件后,您将使用deleteLater()函数删除原始小部件。如果在这种情况下,那么由于_drag->exec()
会阻止事件,因此对于Windows平台tit来说会很好用,如果是mac或Linux,则不会阻止事件。这样,_drag->exec()
事件在执行事件时就获得了空指针。
我知道此deleteLater()
在控件返回事件循环时删除对象时执行。
通常,deleteLater()在_drag-> exec()完成之前执行。