我想告诉你我的 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)"));
}