Qt: корректное завершение приложения (при закрытие приложения Segmentation fault)

Модератор: Модераторы разделов

Ответить
IMB
Сообщения: 2559
ОС: Debian

Qt: корректное завершение приложения

Сообщение IMB »

Доброго дня!

Код: Выделить всё

void MainWindow::on_actionQuit_triggered()
{
    qDebug("destroy()");
    destroy();
}

MainWindow::~MainWindow()
{
    qDebug("~MainWindow");
    if (ui->actionJPEG->isChecked()) {
        qDebug("ui->actionJPEG->isChecked()");
        on_actionJPEG_triggered(false);
    }
    if (ui->actionRtsp->isChecked()) {
        qDebug("ui->actionRtsp->isChecked()");
        on_actionRtsp_triggered(false);
    }
    if (is_connected) {
        qDebug("is_connected");
        server_connect();
    }
    if (ui->actionDebug_output->isChecked()) {
        qDebug("ui->actionDebug_output->isChecked()");
        on_actionDebug_output_triggered(false);
    }
    delete socket;
    delete cur_camera;
    delete cur_status;
    delete ui;
}

При закрытии приложения в консоли следующий вывод:

Код: Выделить всё

destroy()
Segmentation fault

Получается, что деструктор не вызывается, но почему?
Вывод GDB:

Код:

[Thread debugging using libthread_db enabled] destroy() Program received signal SIGSEGV, Segmentation fault. 0xb7629109 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4 (gdb) bt #0 0xb7629109 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4 #1 0xb7629b42 in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4 #2 0xb76299fc in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4 #3 0xb76299fc in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4 #4 0xb7628d1f in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4 #5 0xb7824ffe in ?? () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4 #6 0xb761f7e2 in QWidgetPrivate::syncBackingStore() () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4 #7 0xb762ff74 in QWidget::event(QEvent*) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4 #8 0xb7a816d5 in QMainWindow::event(QEvent*) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4 #9 0xb75c6d7c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4 #10 0xb75cab64 in QApplication::notify(QObject*, QEvent*) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4 #11 0xb71c615b in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4 #12 0xb71c7457 in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4 #13 0xb71c763d in QCoreApplication::sendPostedEvents(QObject*, int) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4 #14 0xb71f6344 in ?? () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4 #15 0xb6bfd305 in g_main_context_dispatch () from /lib/libglib-2.0.so.0 #16 0xb6c00fe8 in ?? () from /lib/libglib-2.0.so.0 #17 0xb6c011c8 in g_main_context_iteration () from /lib/libglib-2.0.so.0 #18 0xb71f6741 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4 #19 0xb7687a55 in ?? () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4 #20 0xb71c531d in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4 #21 0xb71c55aa in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4 #22 0xb71c7701 in QCoreApplication::exec() () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4 #23 0xb75c63b7 in QApplication::exec() () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4 #24 0x0804e15f in main ()

Вопрос - как необходимо корректно завершать приложение?
Спасибо.
Спасибо сказали:
IMB
Сообщения: 2559
ОС: Debian

Re: Qt: корректное завершение приложения

Сообщение IMB »

Пока сделал так:

Код: Выделить всё

MainWindow::MainWindow(QWidget *parent)
........................
if (!testAttribute(Qt::WA_DeleteOnClose))
    setAttribute(Qt::WA_DeleteOnClose);
.......................
}

void MainWindow::on_actionQuit_triggered()
{
    close();
}

Сейчас деструктор вызывается, но Segmentation fault остался.
вывод GDB:

Код:

Starting program: /home/user/bin/qtclient [Thread debugging using libthread_db enabled] Program received signal SIGSEGV, Segmentation fault. 0xb6e0ba39 in *__GI___libc_free (mem=0xbffff670) at malloc.c:3725 3725 malloc.c: No such file or directory. in malloc.c (gdb) bt #0 0xb6e0ba39 in *__GI___libc_free (mem=0xbffff670) at malloc.c:3725 #1 0xb6fe1701 in operator delete(void*) () from /usr/lib/libstdc++.so.6 #2 0xb71d7c35 in qDeleteInEventHandler(QObject*) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4 #3 0xb71d99c5 in QObject::event(QEvent*) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4 #4 0xb762f0a5 in QWidget::event(QEvent*) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4 #5 0xb7a816d5 in QMainWindow::event(QEvent*) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4 #6 0xb75c6d7c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4 #7 0xb75cab64 in QApplication::notify(QObject*, QEvent*) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4 #8 0xb71c615b in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4 #9 0xb71c7457 in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4 #10 0xb71c763d in QCoreApplication::sendPostedEvents(QObject*, int) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4 #11 0xb71f6344 in ?? () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4 #12 0xb6bfd305 in g_main_context_dispatch () from /lib/libglib-2.0.so.0 #13 0xb6c00fe8 in ?? () from /lib/libglib-2.0.so.0 #14 0xb6c011c8 in g_main_context_iteration () from /lib/libglib-2.0.so.0 #15 0xb71f6741 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4 #16 0xb7687a55 in ?? () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4 #17 0xb71c531d in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4 #18 0xb71c55aa in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4 #19 0xb71c7701 in QCoreApplication::exec() () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4 #20 0xb75c63b7 in QApplication::exec() () from /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4 #21 0x0804e1df in main ()
Спасибо сказали:
Аватара пользователя
Voral
Сообщения: 1205
ОС: Debian Wheezy (amd64)
Контактная информация:

Re: Qt: корректное завершение приложения

Сообщение Voral »

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

IMB писал(а):
07.07.2011 14:29

Код: Выделить всё

    delete socket;
    delete cur_camera;
    delete cur_status;
    delete ui;

Здесь возможно будет лучше

Код: Выделить всё

    socket->deleteLater();
    delete->deleteLater();
    cur_status->deleteLater();
    ui->deleteLater();



IMB писал(а):
07.07.2011 14:29

Код: Выделить всё

if (is_connected) {
        qDebug("is_connected");
        server_connect();
    }

А здесь точно не должен быть что то типа

Код: Выделить всё

server_[b]dis[/b]connect();
?


То что не убивает нас, делает нас сильнее! © Ницше.
When life puts you in tough situations, don’t say "why me". Just say "try me © ?
Спасибо сказали:
IMB
Сообщения: 2559
ОС: Debian

Re: Qt: корректное завершение приложения

Сообщение IMB »

Voral писал(а):
07.07.2011 18:07
IMB писал(а):
07.07.2011 14:29

Код: Выделить всё

if (is_connected) {
        qDebug("is_connected");
        server_connect();
    }

А здесь точно не должен быть что то типа

Код: Выделить всё

server_[b]dis[/b]connect();
?

Код: Выделить всё

bool    is_connected;
bool    is_debug;
void MainWindow::server_connect()
{
    server_address = ui->server_address->text().trimmed();
    server_port = ui->server_port->text().trimmed().toInt();

    if (is_connected) {
        is_connected = false;
        cur_stream = STREAM_UNKNOW;
        socket->disconnectFromHost();
        disconnect(socket, SIGNAL(readyRead()), this, SLOT(read_answer()));
        if (is_debug) {
            QString str = QString(tr("disconnected from %1:%2")).
                    arg(server_address).
                    arg(server_port);
            debug->add_data(str);
        }
    } else if (server_port >= MIN_PORT && server_address.length() > 0) {
        socket->connectToHost(server_address, server_port,
                              QIODevice::ReadWrite);
        if (QAbstractSocket::ConnectedState == socket->state()) {
            is_connected = true;
            if (is_debug) {
                QString str = QString(tr("connected to %1:%2")).
                        arg(server_address).
                        arg(server_port);
                debug->add_data(str);
            }
            connect(socket, SIGNAL(readyRead()), this, SLOT(read_answer()));
            send_command(COMMAND_CAMERA_TYPE, 0);
            ui->tabWidget->setCurrentIndex(TAB_NETWORK);
            send_command(COMMAND_STREAM_GET_PARAM, 0);
        }
    }

    ui->server_address->setDisabled(is_connected);
    ui->server_port->setDisabled(is_connected);
    ui->tabWidget->setEnabled(is_connected);
    ui->server_connect->setText(is_connected ? tr("Disconnect") :
                                               tr("Connect"));
    switch_menu(is_connected);
    status_bar();
}
Спасибо сказали:
IMB
Сообщения: 2559
ОС: Debian

Re: Qt: корректное завершение приложения

Сообщение IMB »

Меня вот какой момент смущает:
debugoutput

Код: Выделить всё

namespace Ui {
    class DebugOutput;
}

class DebugOutput : public QDialog
{
    Q_OBJECT
.............

DebugOutput::DebugOutput(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::DebugOutput)
{
..............

DebugOutput::~DebugOutput()
{
    delete ui;
}

image.hpp

Код: Выделить всё

namespace Ui {
    class Image;
}

class Image : public QDialog
{
    Q_OBJECT
...............

Image::Image(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Image)
...................

Image::~Image()
{
    delete ui;
}

mainwindow.hpp

Код: Выделить всё

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
..............

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
.............

MainWindow::~MainWindow()
{
    .....................
    delete ui;
}

Т.е. каждый класс имеющий графическое представление содержит объект ui. А я для использования этих классов включаю их заголовочный файлы в mainwindow.hpp, не происходит ли при этом некоего перекрытия namespace Ui?
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Qt: корректное завершение приложения

Сообщение NickLion »

Попробуйте убрать

Код: Выделить всё

delete socket;
Спасибо сказали:
IMB
Сообщения: 2559
ОС: Debian

Re: Qt: корректное завершение приложения

Сообщение IMB »

Попробовал, ничего не изменилось.
Но, по-моему, если я выделяю память использую new, я должен потом её освободить через delete, а в конструкторе я выполняю socket = new QUdpSocket(this).
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Qt: корректное завершение приложения

Сообщение NickLion »

Да, я пропустил, что до этого деструктор вообще не вызывался и падало. Просто согласен с Voral, что похоже повторно удаляется уже удалённый объект, а сокет - это вполне претендент быть удалённым в disconnect с помощью deleteLater(). Если выложить полные исходники невозможно, то попробуйте применить valgrind. Часто помогает эта штука.

PS по поводу namespace Ui - да, они совмещаются, но классы то разные, а переменные хоть и с одним именем, но в разных классах - так что проблемы нет.
Спасибо сказали:
IMB
Сообщения: 2559
ОС: Debian

Re: Qt: корректное завершение приложения

Сообщение IMB »

Не затруднит ли помочь разобраться в выводе valgrind?
Итак, что я сделал - запустил программу, активировал вывод отладочной информации в отдельное окно, соединился с сервером, запросил несколько параметров с сервера и завершил программу через on_actionQuit_triggered(), вызывает close().

Код:

$ LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH valgrind ./qtclient ==22967== Memcheck, a memory error detector ==22967== Copyright © 2002-2010, and GNU GPL'd, by Julian Seward et al. ==22967== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info ==22967== Command: ./qtclient ==22967== ==22967== Invalid free() / delete / delete[] ==22967== at 0x4023881: operator delete(void*) (vg_replace_malloc.c:387) ==22967== by 0x8050AF6: MainWindow::~MainWindow() (mainwindow.cpp:76) ==22967== by 0x4E86C34: qDeleteInEventHandler(QObject*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4.7.3) ==22967== by 0x4E889C4: QObject::event(QEvent*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4.7.3) ==22967== by 0x42150A4: QWidget::event(QEvent*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4.7.3) ==22967== by 0x46676D4: QMainWindow::event(QEvent*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4.7.3) ==22967== by 0x41ACD7B: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4.7.3) ==22967== by 0x41B0B63: QApplication::notify(QObject*, QEvent*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4.7.3) ==22967== by 0x4E7515A: QCoreApplication::notifyInternal(QObject*, QEvent*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4.7.3) ==22967== by 0x4E76456: QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4.7.3) ==22967== by 0x4E7663C: QCoreApplication::sendPostedEvents(QObject*, int) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4.7.3) ==22967== by 0x4EA5343: ??? (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4.7.3) ==22967== Address 0xbefee5e0 is on thread 1's stack ==22967== ==22967== Invalid read of size 4 ==22967== at 0x805075B: MainWindow::~MainWindow() (mainwindow.cpp:64) ==22967== by 0x804E498: main (in /home/user/bin/qtclient) ==22967== Address 0x58e6b00 is 56 bytes inside a block of size 552 free'd ==22967== at 0x4023881: operator delete(void*) (vg_replace_malloc.c:387) ==22967== by 0x8050A44: MainWindow::~MainWindow() (mainwindow.cpp:75) ==22967== by 0x4E86C34: qDeleteInEventHandler(QObject*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4.7.3) ==22967== by 0x4E889C4: QObject::event(QEvent*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4.7.3) ==22967== by 0x42150A4: QWidget::event(QEvent*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4.7.3) ==22967== by 0x46676D4: QMainWindow::event(QEvent*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4.7.3) ==22967== by 0x41ACD7B: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4.7.3) ==22967== by 0x41B0B63: QApplication::notify(QObject*, QEvent*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4.7.3) ==22967== by 0x4E7515A: QCoreApplication::notifyInternal(QObject*, QEvent*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4.7.3) ==22967== by 0x4E76456: QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4.7.3) ==22967== by 0x4E7663C: QCoreApplication::sendPostedEvents(QObject*, int) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4.7.3) ==22967== by 0x4EA5343: ??? (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4.7.3) ==22967== ==22967== Invalid read of size 4 ==22967== at 0x41A5207: QAction::isChecked() const (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4.7.3) ==22967== by 0x804E498: main (in /home/user/bin/qtclient) ==22967== Address 0x590aae4 is 4 bytes inside a block of size 8 free'd ==22967== at 0x4023881: operator delete(void*) (vg_replace_malloc.c:387) ==22967== by 0x41A5A16: QAction::~QAction() (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4.7.3) ==22967== by 0x4E87F2B: QObjectPrivate::deleteChildren() (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4.7.3) ==22967== by 0x420CF2F: QWidget::~QWidget() (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4.7.3) ==22967== by 0x4665700: QMainWindow::~QMainWindow() (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4.7.3) ==22967== by 0x8050AE2: MainWindow::~MainWindow() (mainwindow.cpp:76) ==22967== by 0x4E86C34: qDeleteInEventHandler(QObject*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4.7.3) ==22967== by 0x4E889C4: QObject::event(QEvent*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtCore.so.4.7.3) ==22967== by 0x42150A4: QWidget::event(QEvent*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4.7.3) ==22967== by 0x46676D4: QMainWindow::event(QEvent*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4.7.3) ==22967== by 0x41ACD7B: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4.7.3) ==22967== by 0x41B0B63: QApplication::notify(QObject*, QEvent*) (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4.7.3) ==22967== ==22967== Invalid read of size 1 ==22967== at 0x41A520A: QAction::isChecked() const (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4.7.3) ==22967== by 0x804E498: main (in /home/user/bin/qtclient) ==22967== Address 0x9c is not stack'd, malloc'd or (recently) free'd ==22967== ==22967== ==22967== Process terminating with default action of signal 11 (SIGSEGV) ==22967== Access not within mapped region at address 0x9C ==22967== at 0x41A520A: QAction::isChecked() const (in /opt/QtSDK4.7/Desktop/Qt/473/gcc/lib/libQtGui.so.4.7.3) ==22967== by 0x804E498: main (in /home/user/bin/qtclient) ==22967== If you believe this happened as a result of a stack ==22967== overflow in your program's main thread (unlikely but ==22967== possible), you can try to increase the size of the ==22967== main thread stack using the --main-stacksize= flag. ==22967== The main thread stack size used in this run was 8388608. ==22967== ==22967== HEAP SUMMARY: ==22967== in use at exit: 1,030,402 bytes in 5,732 blocks ==22967== total heap usage: 69,612 allocs, 63,881 frees, 12,178,497 bytes allocated ==22967== ==22967== LEAK SUMMARY: ==22967== definitely lost: 856 bytes in 4 blocks ==22967== indirectly lost: 2,720 bytes in 135 blocks ==22967== possibly lost: 173,624 bytes in 1,683 blocks ==22967== still reachable: 853,202 bytes in 3,910 blocks ==22967== suppressed: 0 bytes in 0 blocks ==22967== Rerun with --leak-check=full to see details of leaked memory ==22967== ==22967== For counts of detected and suppressed errors, rerun with: -v ==22967== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 105 from 10) Segmentation fault

Спасибо.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Qt: корректное завершение приложения

Сообщение NickLion »

Ну, не считая утечек памяти, valgrind говорит, что некорректное удаление и до этого обращение к невыделенной или удалённой памяти. А вот вопрос возник, как создаётся экземпляр класса MainWindow?

PS приведите код деструктора с номерами тсрок, пожалуйста :)
Спасибо сказали:
IMB
Сообщения: 2559
ОС: Debian

Re: Qt: корректное завершение приложения

Сообщение IMB »

NickLion писал(а):
08.07.2011 13:36
А вот вопрос возник, как создаётся экземпляр класса MainWindow?

Код: Выделить всё

enum debug_e {
    DEBUG_DISABLED = 0,    ///< отладочный вывод выключен
    DEBUG_ENABLED        ///< отладочный вывод включён
};

enum stream_format_e {
    STREAM_RAW = 0,    ///< RAW 1Gb/s
    STREAM_RGB,        ///< RGB 1Gb/s
    STREAM_YUV420,    ///< YUV420 1Gb/s
    STREAM_YUV422,    ///< YUV422 1Gb/s
    STREAM_H264,    ///< H264 100 Mbit/s
    STREAM_MJPEG,    ///< MJPEG 100 Mbit/s
    STREAM_UNKNOW    ///< неизвесный формат потока
};

qint16 server_port;
QString camera_type;
QString matrix;
bool is_connected;
bool is_debug;
enum stream_format_e cur_stream;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    server_port(QString(DEFAULT_PORT).toInt()),
    camera_type(QString(tr("unknow"))),
    matrix(QString(tr("unknow"))),
    is_connected(false),
    is_debug(DEBUG_DISABLED),
    cur_stream(STREAM_UNKNOW)
{
    ui->setupUi(this);
    if (!testAttribute(Qt::WA_DeleteOnClose))
        setAttribute(Qt::WA_DeleteOnClose);
    setFixedSize(geometry().width(), geometry().height());
    ui->server_port->setText(DEFAULT_PORT);
    ui->image_scale->addItems(QStringList()
                              << tr("none") << tr("skipping") << tr("binning"));
    ui->color_awb->addItems(QStringList() << tr("disabled") << tr("enabled"));
    ui->exposure_mode->addItems(QStringList() << tr("manual") << tr("auto"));
    ui->wdr_mode->insertItem(WDR_MODE_SINGLE, tr("1 point"),
                             QVariant(WDR_MODE_SINGLE));
    ui->wdr_mode->insertItem(WDR_MODE_DUAL, tr("2 point"),
                             QVariant(WDR_MODE_DUAL));
    ui->wdr_mode->insertItem(WDR_MODE_TRIPLE, tr("3 point"),
                             QVariant(WDR_MODE_TRIPLE));
    ui->stream_format->addItems(QStringList() << tr("RAW 1Gb/s")
                                << tr("RGB 1Gb/s") << tr("YUV420 1Gb/s")
                                << tr("YUV422 1Gb/s") << tr("H264 100Mb/s")
                                << tr("MJPEG 100Mb/s"));
    ui->special_ard_mode->addItems(QStringList() << tr("disabled")
                                   << tr("enabled"));
    ui->special_matrix_sync->addItems(QStringList() << tr("none")
                                      << tr("trigger") << tr("register"));
    switch_menu(is_connected);
    statusBar()->addWidget(new QLabel(tr("Status")));
    cur_status = new QLabel("");
    statusBar()->addWidget(cur_status, 1);
    statusBar()->addWidget(new QLabel(tr("Camera")));
    cur_camera = new QLabel("");
    statusBar()->addWidget(cur_camera, 1);
    status_bar();
    socket = new QUdpSocket(this);
}

NickLion писал(а):
08.07.2011 13:36
PS приведите код деструктора с номерами тсрок, пожалуйста :)

Код: Выделить всё

MainWindow::~MainWindow()
{
64    if (ui->actionJPEG->isChecked())
65        on_actionJPEG_triggered(false);
66    if (ui->actionRtsp->isChecked())
67        on_actionRtsp_triggered(false);
68    if (is_connected)
69        server_connect(false);
70    if (ui->actionDebug_output->isChecked())
71        on_actionDebug_output_triggered(false);
72    delete socket;
73    delete cur_camera;
74    delete cur_status;
75    delete ui;
}
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Qt: корректное завершение приложения

Сообщение NickLion »

Не, где именно создаётся сам объект MainWindow. Такое впечатление, что как раз он и удаляется дважды.
Спасибо сказали:
IMB
Сообщения: 2559
ОС: Debian

Re: Qt: корректное завершение приложения

Сообщение IMB »

main.cpp

Код: Выделить всё

#include <QtGui/QApplication>
#include <QTranslator>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QTranslator appTranslator;
    appTranslator.load("qtclient_" + QLocale::system().name(), ".");
    a.installTranslator(&appTranslator);

    MainWindow w;
    w.show();


    return a.exec();
}
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Qt: корректное завершение приложения

Сообщение NickLion »

Уберите

Код: Выделить всё

if (!testAttribute(Qt::WA_DeleteOnClose))
    setAttribute(Qt::WA_DeleteOnClose);
Спасибо сказали:
IMB
Сообщения: 2559
ОС: Debian

Re: Qt: корректное завершение приложения

Сообщение IMB »

Хмм, Segmentation fault вроде пропал, но теперь не вызывается декструктор другого окна, т.е. оно остаётся работающим.
Буду разбираться почему не сработала проверку ui->actionJPEG->isChecked().
Спасибо сказали:
Аватара пользователя
eddy
Сообщения: 3321
Статус: Красный глаз тролля
ОС: ArchLinux
Контактная информация:

Re: Qt: корректное завершение приложения

Сообщение eddy »

IMB, а что разрабатываете, если не секрет?
RTFM
-------
KOI8-R - патриотичная кодировка Изображение
Спасибо сказали:
IMB
Сообщения: 2559
ОС: Debian

Re: Qt: корректное завершение приложения

Сообщение IMB »

Не секрет, сейчас это графический клиент для управления IP-камерой по собственному протоколу.
Мой дебют в написании программ с графическим интерфейсой, ну и параллельно практикуюсь в C++.
Спасибо сказали:
IMB
Сообщения: 2559
ОС: Debian

Re: Qt: корректное завершение приложения

Сообщение IMB »

Нет, этот вариант не годится, деструктор приложения вызывается только после закрытия последнего окна. А надо что бы закрытие центрального окна завершало приложение.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Qt: корректное завершение приложения

Сообщение NickLion »

IMB, смотрите в сторону Qt::WA_QuitOnClose

UPD т.е. с "неважных" окон надо его снять
Спасибо сказали:
IMB
Сообщения: 2559
ОС: Debian

Re: Qt: корректное завершение приложения

Сообщение IMB »

Не затруднит объяснить почему при установке Qt::WA_DeleteOnClose на MainWindow были эти проблемы? И что изменилось при снятии Qt::WA_QuitOnClose?
Документацию я прочитал, но она достаточно кратка в описании данных опций.
Спасибо.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Qt: корректное завершение приложения

Сообщение NickLion »

Qt::WA_DeleteOnClose - вызывается delete для объекта при закрытии. Тут две проблемы, объект был создан в main в стеке, а не куче, для него:
1) вызывается деструктор автоматически;
2) удаление памяти производится не при помощи delete, а просто увеличением значения регистра RSP/ESP (при выходе из функции).
а вызов delete приводил к повторному вызову деструктора и попытке освобождения памяти, которая не принадлежит куче.

Qt::WA_QuitOnClose - название немного двояко можно понимать, как по мне. В общем-то, пока есть хотя бы один из виджетов с этим флагом - приложение работает. Как только будет уничтожен последний - будет осуществлён выход из приложения.

Можно было бы обойти это вызовом QCoreApplication::exit(0), но так, имхо, правильнее.
Спасибо сказали:
IMB
Сообщения: 2559
ОС: Debian

Re: Qt: корректное завершение приложения

Сообщение IMB »

Странно, Бланшет с товарищами применяет именно Qt::WA_DeleteOnClose при работе с мультиоконным приложением.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Qt: корректное завершение приложения

Сообщение NickLion »

IMB писал(а):
08.07.2011 16:28
Странно, Бланшет с товарищами применяет именно Qt::WA_DeleteOnClose при работе с мультиоконным приложением.

Это можно делать, но в таком случае main должен выглядеть примерно так:

Код: Выделить всё

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QTranslator appTranslator;
    appTranslator.load("qtclient_" + QLocale::system().name(), ".");
    a.installTranslator(&appTranslator);

    MainWindow* w = new MainWindow();
    w->show();

    return a.exec();
}

Т.е. в стеке будет лишь указатель, а сам объект в куче.

UPD Бланшет не читал, но думаю что-то такое там
Спасибо сказали:
Ответить