2015-07-14 9 views
4

я следующий случай использования (на самом деле не имеет смысла, потому что это сведено к минимуму из реальной жизни рабочего примера, но я думаю, что это все еще технически правильно):Неужели Q3ListView не может отменить регистрацию из хранилища резервных копий Qt или неправильный код?

class Dialog : public QDialog 
{ 
public: 
    Dialog(QWidget* parent) 
    : QDialog(parent) 
    { 
     new Q3ListView(this); // this will crash 
// new QWidget(this); // this won't crash 
    } 
}; 

В зависимости от того, что добавляются к Dialog программа выйдет из строя или нет при удалении экземпляра Dialog (как указано комментариями в фрагменте), но только когда флаги основного окна были изменены. Вот код для MainWindow класса, который использует Dialog:

class MainWindow : public QMainWindow 
{ 
public: 
    // the fact that the widget (dialog) below 
    // has no chance to show seems irrelevant. 
    // In the real scenario I have, the widget is shown on 
    // the screen and is closed by the user. 
    // I've just put the whole sequence of pieces of code 
    // that result from signal/slot calls, that in turn 
    // result from a point&click scenario in our application 
    // into the following function for brevity. 
    void go() 
    {   
     auto dialog = new Dialog(this); 
     dialog->show(); 
     dialog->close(); 

     disableAlwaysOnTop(); 

     delete dialog; // or dialog->deleteLater(); 
    } 

    void disableAlwaysOnTop() 
    { 
     setAttribute(Qt::WA_Resized, true); 

     Qt::WindowFlags flags = windowFlags(); 
     setWindowFlags(flags^(Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint)); 

     setVisible(true); 
    } 
}; 

и реализация main:

int main(int argc, char** argv) 
{ 
    QApplication app(argc, argv); 
    MainWindow mainWindow; 
    mainWindow.show(); 
    mainWindow.go(); 
    return app.exec(); 
} 

Все линии, кажется, необходимо воспроизвести аварии.

Это ошибка в Qt, или я делаю что-то неправильно?

Разрешено вручную удалять дочерние элементы виджета, и они должны автоматически отменить регистрацию у своих родителей, как указано в цитате из приведенного ниже руководства. В моем реальном случае виджет удаляется, чтобы исчезнуть из графического интерфейса, и он работает в случае других комбинаций виджетов. Как указано в комментарии выше, изменение delete dialog; на dialog->deleteLater(); не помогает.

Кажется, что существует проблема, заключающаяся в удалении экземпляра Q3ListView из резервного хранилища Qt, вот трассировки стека:

QtGuid4.dll QWidgetBackingStore :: staticContents (QWidget * Родитель, Const QRect & withinClipRect) линия 499 C++

QtGuid4.dll! QWidgetBackingStore :: синхронизации() линия 1200 C++

QtGuid4.dll! QWidgetPrivate :: syncBackingStore() Line 1896 C++

QtGuid4.dll! QWidget :: события (QEvent * событие) Линия 8694 C++

QtGuid4.dll! QMainWindow :: события (QEvent * событие) Линия 1479 C++

QtGuid4.dll! QApplicationPrivate :: notify_helper (QObject * приемник, QEvent * е) линия 4565 C++

QtGuid4.dll! QApplication :: Notify (QObject * приемник, QEvent * е) линия 4530 C++

QtCored4.dll! QCoreApplication :: notifyInternal (QObject *, событие QEvent *) Строка 955 C++

QtCored4.dll! QCoreApplication :: SendEvent (QObject * приемник, QEvent * событие) Линия 231 C++

QtCored4.dll! QCoreApplicationPrivate :: sendPostedEvents (QObject * приемник, INT event_type, QThreadData * данные) Линия 1579 C++

QtCored4.dll!qt_internal_proc (HWND__ * HWND, неподписанных INT сообщение, неподписанные __int64 сор, __int64 ПОЛ) Линия 498 C++

[External Code]

QtCored4.dll! QEventDispatcherWin32 :: processEvents (QFlags флаги) Строка 823 C++

QtGuid4.dll! QGuiEventDispatcherWin32 :: processEvents (QFlags флаги) Линия 1216 C++

QtCored4.dll! QEventLoop :: processEvents (QFlags флаги) Линия 150 C++

QtCored4.dll! QEventLoop :: Exec (QFlags флаги) Строка 20 4 C++

QtCored4.dll! QCoreApplication :: Exec() Line 1227 C++

QtGuid4.dll! QApplication :: Exec() Line 3824 C++

qt_bug.exe! Основной (интермедиат ARGC, голец * * ARGV) линия 60 C++

И кусок кода в Qt, который пытается использовать указатель на удаленный объект в строке, указанной в трассировке стека:

for (int i = 0; i < count; ++i) { 
    QWidget *w = staticWidgets.at(i); 
    QWidgetPrivate *wd = w->d_func(); 
    if (!wd->isOpaque || !wd->extra || wd->extra->staticContentsSize.isEmpty() // **** 
     || !w->isVisible() || (parent && !parent->isAncestorOf(w))) { 
     continue; 
    } 

(wd указывает на удаленный объект по строке, помеченной комментарием).

Отказ от ответственности: Я знаю, что существует более элегантные решения, но это унаследованный код, и в соответствии с Qt's manual:

Вы можете также удалять дочерние объекты самостоятельно, и они будут удалены от своих родителей.

этот код действителен.

Мы воспроизвели проблему в Windows 7 (MSVC 2010 SP1, CL16), Windows 8 (MSVC 2013 U4, CL 18) и Fedora 20 (GCC 4.8.3).

+0

Похоже подлинному Qt ошибка. Это угловой случай: кажется, вы не должны удалять созданные экземпляры и отображаемые виджеты до того, как цикл событий имел шанс запустить. Я не думаю, что это специфично для Q3ListView. Моя ставка заключается в том, что если вы измените 'delete dialog' на' dialog-> deleteLater() ', это не сработает. Возможно, если вы вставляете 'qApp-> processEvents()' перед 'delete', он также не будет аварийно завершен. Пожалуйста, сообщите нам, на какой платформе он включен, так как это важно. Я могу попытаться воспроизвести его. –

+0

TL; DR: Ваш код не является неправильным, но я сомневаюсь, что в базе кода Qt есть много тестов, чтобы убедиться, что отображаемые, отображаемые виджеты могут быть удалены до того, как цикл события исчерпан. Бьюсь об заклад, такие махинации могут падать и в Qt 5. –

+0

@KubaOber Спасибо за ваш вклад. Я забыл упомянуть, что я пробовал 'dialog-> deleteLater()' и, к сожалению, это не помогло. Мы воспроизвели крах в Windows 7, Windows 8 и Arch Linux. Я уточню вопрос. – BartoszKP

ответ

0

Я подал bug report. Поскольку это касается старой версии библиотеки, нет надежды на ее исправление.

Мы последовательно удаляя qt3support в любом случае и так все уточнено;)