为啥这个代码在 w.show() 调用中会出现段错误?
Posted
技术标签:
【中文标题】为啥这个代码在 w.show() 调用中会出现段错误?【英文标题】:Why does this code segfault on the w.show() call?为什么这个代码在 w.show() 调用中会出现段错误? 【发布时间】:2014-08-11 10:10:25 【问题描述】:主题说明了一切,代码如下:
我正在使用带有 qt-opensource-windows-x86-mingw482_opengl-5.3.1 的 windows 7 64 位
我在下面发布了受影响的代码。在调试崩溃时,我在 main.cpp 文件中的 w.show() 行上得到一个段错误
编辑: 抱歉忘记补充,如果我注释掉该行,它不会崩溃:
//mainLayout->addLayout(oldLayout,0,0,1,1,Qt::AlignLeft);
然后它会正确显示带有小部件的主窗口,但是当我尝试向布局添加布局时,它崩溃了...
main.cpp:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
主窗口.cpp
#include <QLabel>
#include <QString>
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
setupWidgets();
void MainWindow::setupWidgets()
mainWidget = new QWidget;
mainLayout = new QGridLayout;
setupOld();
setCentralWidget(mainWidget);
mainWidget->setLayout(mainLayout);
mainLayout->addLayout(oldLayout,0,0,1,1,Qt::AlignLeft);
void MainWindow::setupOld()
oldLayout = new QGridLayout;
oldX = new QDoubleSpinBox;
oldX->setRange(minNum,maxNum);
oldX->setDecimals(precision);
oldX->setSuffix(suffix);
oldY = new QDoubleSpinBox;
oldY->setRange(minNum,maxNum);
oldY->setDecimals(precision);
oldY->setSuffix(suffix);
oldZ = new QDoubleSpinBox;
oldZ->setRange(minNum,maxNum);
oldZ->setDecimals(precision);
oldZ->setSuffix(suffix);
QLabel lblX, lblY, lblZ;
lblX.setText("Old X Coord: ");
lblY.setText("Old Y Coord: ");
lblZ.setText("Old Z Coord: ");
oldLayout->addWidget(&lblX,0,0,1,1,Qt::AlignLeft);
oldLayout->addWidget(oldX,0,1,1,1,Qt::AlignLeft);
oldLayout->addWidget(&lblY,1,0,1,1,Qt::AlignLeft);
oldLayout->addWidget(oldY,1,1,1,1,Qt::AlignLeft);
oldLayout->addWidget(&lblZ,2,0,1,1,Qt::AlignLeft);
oldLayout->addWidget(oldZ,2,1,1,1,Qt::AlignLeft);
【问题讨论】:
这通常是由空指针引起的,检查你的对象的属性 默认构造函数在哪里? @quantdev 通常是MainWindow(QWidget* parent=0)
(也就是使用默认参数)
【参考方案1】:
我认为原因在于以下代码:
QLabel lblX, lblY, lblZ;
[..]
oldLayout->addWidget(&lblX,0,0,1,1,Qt::AlignLeft);
您在堆栈中创建标签对象并在布局中使用它们。执行存在MainWindow::setupOld()
函数后,标签正在删除,因此您的布局包含对已删除对象的引用。
要解决这个问题,您需要像为QDoubleSpinBox
es 那样创建从堆分配内存的标签:
QLabel *lblX = new QLabel("Old X Coord: ");
[..]
oldLayout->addWidget(lblX,0,0,1,1,Qt::AlignLeft);
【讨论】:
@vahancho 谢谢,是的,创建了指针标签,现在它可以工作了:)【参考方案2】:下面的作品。请注意我是如何剔除重复代码,将所有对象作为MainWindow
的直接成员,并在构造函数中利用初始化列表的。
如果您不想使用它的其他功能(停靠区、状态栏等),您不必使用QMainWindow
。在下面的代码中,您可以轻松地将QMainWindow
替换为QWidget
,并进行以下其他更改:
在this
而不是m_central
上设置布局,
删除setCentralWidget
调用。
#include <QApplication>
#include <QMainWindow>
#include <QLabel>
#include <QGridLayout>
#include <QDoubleSpinBox>
class MainWindow : public QMainWindow
QWidget m_central;
QGridLayout m_centralLayout;
QDoubleSpinBox m_oldX, m_oldY, m_oldZ;
QLabel m_lblX, m_lblY, m_lblZ;
public:
MainWindow(QWidget * parent = 0, Qt::WindowFlags flags = 0);
;
MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags flags) :
QMainWindow(parent, flags),
m_centralLayout(&m_central),
m_lblX("Old X Coord: "),
m_lblY("Old Y Coord: "),
m_lblZ("Old Z Coord: ")
QList<QDoubleSpinBox*> spins;
spins << &m_oldX << &m_oldY << &m_oldZ;
int i = 0;
foreach (QDoubleSpinBox * spin, spins)
spin->setRange(0.0, 1.0);
spin->setDecimals(3);
spin->setSuffix(" km");
m_centralLayout.addWidget(spin, i++, 1);
m_centralLayout.addWidget(&m_lblX, 0, 0);
m_centralLayout.addWidget(&m_lblY, 1, 0);
m_centralLayout.addWidget(&m_lblZ, 2, 0);
setCentralWidget(&m_central);
int main(int argc, char *argv[])
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
【讨论】:
以上是关于为啥这个代码在 w.show() 调用中会出现段错误?的主要内容,如果未能解决你的问题,请参考以下文章