1

我想告诉你我的 Qt 应用程序有一个奇怪的问题。

我有两个窗口:第一个是 QMainWindow,第二个是 QDialog 派生类。QMainWindow 显示了一个 QDialog,它有一个表单和一个 QPushButton,以便使用 QFileDialog::getOpenFileName。

当我第一次运行我的应用程序时(系统启动后),我遇到了内存问题:

*** Error in `/home/nico/Documents/Projets_QtCreator/build-utilitaireTwsGraph-Kit_test-Debug/utilitaireTwsGraph': free(): invalid pointer: 0x000000000090cd40 ***

为了重现这个问题,我必须重新启动我的系统,所以我认为这是一个典型的内存损坏错误。我做了一些调查:

首先,我尝试使用 gdb 找到犯罪行。它告诉我:

Program received signal SIGABRT, Aborted.
0x00007ffff63ac037 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56  ../nptl/sysdeps/unix/sysv/linux/raise.c: Aucun fichier ou dossier de ce type.

堆栈跟踪显示:

(gdb) where
#0  0x00007ffff63ac037 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1  0x00007ffff63af698 in __GI_abort () at abort.c:90
#2  0x00007ffff63e95ab in __libc_message (do_abort=do_abort@entry=2, fmt=fmt@entry=0x7ffff64fc860 "*** Error in `%s': %s: 0x%s ***\n")
    at ../sysdeps/unix/sysv/linux/libc_fatal.c:199
#3  0x00007ffff63f5a46 in malloc_printerr (ptr=0x90cd40, str=0x7ffff64f8825 "free(): invalid pointer", action=3) at malloc.c:4902
#4  _int_free (av=<optimized out>, p=0x90cd30, have_lock=0) at malloc.c:3758
#5  0x00007fffeea21d76 in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#6  0x00007ffff50f6538 in g_object_unref () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#7  0x00007fffeea0f21b in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#8  0x00007fffeea13584 in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#9  0x00007ffff50f6538 in g_object_unref () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#10 0x00007fffee9b59ea in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#11 0x00007fffee9eaf5f in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#12 0x00007ffff50f155e in g_closure_invoke () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#13 0x00007ffff51030e4 in ?? () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#14 0x00007ffff510ad11 in g_signal_emit_valist () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#15 0x00007ffff510af92 in g_signal_emit () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#16 0x00007fffeea8f580 in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#17 0x00007ffff50f7640 in g_object_run_dispose () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#18 0x00007fffee9b59ea in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#19 0x00007fffee9eaf5f in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#20 0x00007ffff50f155e in g_closure_invoke () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#21 0x00007ffff51030e4 in ?? () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#22 0x00007ffff510ad11 in g_signal_emit_valist () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#23 0x00007ffff510af92 in g_signal_emit () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#24 0x00007fffeea8f580 in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#25 0x00007ffff50f7640 in g_object_run_dispose () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#26 0x00007fffee9eaf5f in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#27 0x00007ffff50f1620 in g_closure_invoke () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#28 0x00007ffff51030e4 in ?? () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#29 0x00007ffff510ad11 in g_signal_emit_valist () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#30 0x00007ffff510af92 in g_signal_emit () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#31 0x00007fffeea8f580 in ?? () from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#32 0x00007ffff50f7640 in g_object_run_dispose () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#33 0x00007ffff7684879 in ?? () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#34 0x00007ffff77c537a in QFileDialog::getOpenFileName(QWidget*, QString const&, QString const&, QString const&, QString*, QFlags<QFileDialog::Option>) ()
   from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#35 0x0000000000409277 in FenetreSelectionStatusMonitor::selectionnerStatusMonitor (this=0x825710)
    at ../utilitaireTwsGraph/dev/src/vue/fenetreSelectionStatusMonitor.cpp:89

所以我猜这个问题出在我的 getOpenFileName 调用中。

然后,我删除了我的 QDialog 的modality属性(没有效果),我使用了 valgrind 但它没有帮助我:

 Invalid free() / delete / delete[] / realloc()
==2237==    at 0x4C2BA6C: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2237==    by 0xE194D75: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.17)
==2237==    by 0x78F3537: g_object_unref (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3600.0)
==2237==    by 0xE18221A: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.17)
==2237==    by 0xE186583: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.17)
==2237==    by 0x78F3537: g_object_unref (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3600.0)
==2237==    by 0xE1289E9: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.17)
==2237==    by 0xE15DF5E: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.17)
==2237==    by 0x78EE55D: g_closure_invoke (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3600.0)
==2237==    by 0x79000E3: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3600.0)
==2237==    by 0x7907D10: g_signal_emit_valist (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3600.0)
==2237==    by 0x7907F91: g_signal_emit (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3600.0)
==2237==  Address 0x155066d0 is 720 bytes inside a block of size 1,008 alloc'd
==2237==    at 0x4C2A896: memalign (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2237==    by 0x4C2A987: posix_memalign (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2237==    by 0x6F22A07: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.3600.0)
==2237==    by 0x6F6C3EB: g_slice_alloc (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.3600.0)
==2237==    by 0x6F6C445: g_slice_alloc0 (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.3600.0)
==2237==    by 0x790E8C4: g_type_create_instance (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3600.0)
==2237==    by 0x78F9A4B: g_param_spec_internal (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3600.0)
==2237==    by 0x78FDA11: g_param_spec_object (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3600.0)
==2237==    by 0xD98D4CB: ??? (in /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.3600.0)
==2237==    by 0x790C955: g_type_class_ref (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3600.0)
==2237==    by 0x78F535C: g_object_new_valist (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3600.0)
==2237==    by 0x78F5803: g_object_new (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.3600.0)
==2237==

当我不使用本机对话框时,我没有这个问题。所以我认为这可能是系统依赖或包错误,但我有一个使用 GetOpenFileName (完全相同的调用)的其他应用程序,我可以编译它并且它可以工作。

GetOpenFileName 调用位于 Qt Slot 中:

void FenetreSelectionStatusMonitor::selectionnerStatusMonitor() {
    QFileDialog::getOpenFileName(this, tr("Fichier descriptif du status monitor"), "/home",tr("Lst (*.lst)"));
}

头文件(我删除了无用的声明):

#ifndef FENETRE_SELECTION_STATUS_MONITOR
#define FENETRE_SELECTION_STATUS_MONITOR

#include <QFileDialog>

class FenetreSelectionStatusMonitor : public QDialog {
    Q_OBJECT
    public:
        FenetreSelectionStatusMonitor(int hauteur, int largeur, QWidget* parent);

    private slots:
        void selectionnerStatusMonitor();
};

#endif // FENETRE_SELECTION_STATUS_MONITOR

我想我会尝试重新安装我的 qt 包,因为我现在没有任何想法。我检查了调用参数,但没有找到任何东西。由于我的程序缺乏稳定性,我在问我问题。而且即使我没有问题,我也不知道如何证明我的程序不会崩溃并且没有内存泄漏(带有库的valgrind很难使用),真是令人绝望!

非常感谢您阅读这篇文章,希望您能帮助我:)

编辑:我买了一个新项目,只有一个简单的 QMainWindow 调用一个调用 GetOpenFileName 的 QDialog。我也有完全一样的问题。

这个新项目有 2 个类和一个主类:

主.cpp:

#include <QApplication>
#include "mainWindowTest.h"

int main(int argc, char** argv) {
    QApplication app(argc,argv);
    MainWindowTest window;
    window.show();

    return app.exec();
}

主窗口测试.h:

#ifndef MAIN_WINDOW_TEST_H
#define MAIN_WINDOW_TEST_H

#include <QMainWindow>
#include <QWidget>
#include <QHBoxLayout>
#include <QPushButton>
#include "dialogTest.h"

class MainWindowTest : public QMainWindow {
    Q_OBJECT

    public:
        MainWindowTest();

    private slots:
        void openDialog();
};

#endif //MAIN_WINDOW_TEST_H    

对话测试.h:

#ifndef DIALOG_TEST_H
#define DIALOG_TEST_H

#include <QDialog>
#include <QWidget>
#include <QHBoxLayout>
#include <QPushButton>
#include <QFileDialog>

class DialogTest : public QDialog {
    Q_OBJECT

    public:
        DialogTest();

    private slots:
        void openFile();
};

#endif //DIALOG_TEST_H

主窗口测试.cpp

#include "mainWindowTest.h"

MainWindowTest::MainWindowTest() {
    setMinimumSize(200,200);

    QWidget* widget = new QWidget();
    QHBoxLayout* layout = new QHBoxLayout();
    QPushButton* btnOpen = new QPushButton("Open dialog");
    connect(btnOpen, SIGNAL(clicked()), this, SLOT(openDialog()));
    layout->addWidget(btnOpen);

    widget->setLayout(layout);
    setCentralWidget(widget);
}

void MainWindowTest::openDialog() {
    DialogTest dialog;
    dialog.exec();
}

对话框测试.cpp

#include "dialogTest.h"

DialogTest::DialogTest() {
    QHBoxLayout* layout = new QHBoxLayout();
    QPushButton* btnOpen = new QPushButton("Open file");
    connect(btnOpen, SIGNAL(clicked()), this, SLOT(openFile()));
    layout->addWidget(btnOpen);

    setLayout(layout);
}

void DialogTest::openFile() {
    QFileDialog::getOpenFileName(this, tr("Fichier descriptif du status monitor"), "/home", tr("Lst (*.lst)"));
}
4

0 回答 0