关于C#:在QWidget的子类中调用width()、height()、size()或rect()以segfault结尾 | 珊瑚贝

Calling width(), height(), size() or rect() inside subclass of QWidget ends with segfault


我对QWidget 的width()、height()、size() 或rect() 功能有疑问;当它被调用时,它会出现段错误。它是 Qt 4.7。

这是有问题的类的标题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class PlotCanvas : public QWidget
{
    void paintEvent(QPaintEvent * e);
    uint64_t smallestDiv();
    uint64_t longestLength();
    void drawGrid(QPainter * painter);
    QVector<Plot*> plots;
    int calculateHeight() const;
    int calculateWidth() const;
    uint32_t cursorPosition;
public:
    PlotCanvas(QWidget * parent = 0) : QWidget(parent)
    {
        setStyleSheet(“background-color: black”);
        setAutoFillBackground(true);
        setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
        setFocusPolicy(Qt::StrongFocus);
        update();
    }
    void addPlot(Plot * plot);
    int getDivCount();
};

和实际的段错误代码:

1
2
3
4
5
6
7
int PlotCanvas::getDivCount()
{
   QRect bounds = rect(); //segfaults
   qDebug() << bounds.size().width();
   qDebug() << bounds.size().height();
   return 10;
}

追溯到Qt的qrect.h:

1
2
inline int QRect::width() const
{ return  x2 x1 + 1; } //this line finally kills it

这似乎是在 QWidget 中没有正确初始化的东西,但我不知道是什么,因为如您所见,我并没有真正改变 QWidget 的初始化。

PlotCanvas 小部件位于 QAbstractScrollArea 的子类中(尚未实现,所以它只是普通的 QAbstractScrollArea:

1
2
3
4
5
6
7
8
class PlotCanvasScrollArea : public QAbstractScrollArea
{
public:
    PlotCanvasScrollArea(QWidget * parent = 0) : QAbstractScrollArea(parent)
    {

    }
};

我只需要确定 QWidget 绘画区域的大小,因为我在转换图中进行绘图,并且我需要知道多少时间分割适合当前的小部件大小,因为显然应用程序窗口是可调整大小的。

编辑:

构造PlotCanvas的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Board(QString & name) : name(name)
{
    hbox = new QHBoxLayout();
    commonKnobGroup = new QGroupBox(“Common settings:”);
    commonKnobGroup>setMinimumWidth(190);
    commonKnobGroup>setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
    commonKnobs = new CommonKnobs(commonKnobGroup);
    hsplitter = new QSplitter();
    plotGroupBox = new QGroupBox(“Measurement plots:”, hsplitter);
    settingsGroupBox = new QGroupBox(“Plot settings:”, hsplitter);
    plotSplitter = new QSplitter();
    plotHbox = new QHBoxLayout();
    plotHbox>addWidget(plotSplitter);
    plotGroupBox>setLayout(plotHbox);
    settingsVLayout = new QVBoxLayout();
    plotNamesColumn = new QListWidget(plotSplitter);
    scrollArea = new PlotCanvasScrollArea(plotSplitter);
    //scrollArea->setWidgetResizable(true);
    plotsCanvas = new PlotCanvas();
    scrollArea>setViewport(plotsCanvas);
    scrollArea>setBackgroundRole(QPalette::Dark);
    specializedKnobGroup = new QGroupBox(“Probe settings:”);
    plotSettings = new QStackedWidget(specializedKnobGroup);
    settingsVLayout>addWidget(commonKnobGroup);
    settingsVLayout>addWidget(specializedKnobGroup);
    settingsGroupBox>setLayout(settingsVLayout);
    hbox>addWidget(hsplitter);
    setLayout(hbox);
    connect(plotNamesColumn, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), this,
            SLOT(changePageNames(QListWidgetItem*, QListWidgetItem*)));
    connect(commonKnobs, SIGNAL(scaleUpdated()), plotsCanvas, SLOT(update()));

};

编辑2:
完整的堆栈跟踪:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#0  0x000000010000b9ac in QWidget::rect() const at /Volumes/Data/shinji/QtSDK/Desktop/Qt/474/gcc/include/QtGui/qwidget.h:1007
#1  0x000000010000b454 in PlotCanvas::getDivCount() ()
#2  0x000000010000ab39 in Board::getDivCount() ()
#3  0x0000000100009fbc in CommonKnobs::updateScaleByBeginEnd() ()
#4  0x00000001000015b4 in CommonKnobs::qt_metacall(QMetaObject::Call, int, void**) ()
#5  0x0000000100d09b66 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) ()
#6  0x000000010070df9d in QSpinBox::valueChanged(int) ()
#7  0x00000001004d9684 in QSpinBoxPrivate::emitSignals(EmitPolicy, QVariant const&) ()
#8  0x000000010043b321 in QAbstractSpinBoxPrivate::setValue(QVariant const&, EmitPolicy, bool) ()
#9  0x000000010043c11a in QAbstractSpinBoxPrivate::_q_editorTextChanged(QString const&) ()
#10 0x000000010043cca7 in QAbstractSpinBox::qt_metacall(QMetaObject::Call, int, void**) ()
#11 0x000000010070e435 in QSpinBox::qt_metacall(QMetaObject::Call, int, void**) ()
#12 0x0000000100d09b66 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) ()
#13 0x000000010048a1e6 in QLineEdit::textChanged(QString const&) ()
#14 0x000000010048d23a in QLineEdit::qt_metacall(QMetaObject::Call, int, void**) ()
#15 0x0000000100d09b66 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) ()
#16 0x000000010070c9f9 in QLineControl::textChanged(QString const&) ()
#17 0x0000000100494337 in QLineControl::finishChange(int, bool, bool) ()
#18 0x0000000100496664 in QLineControl::processKeyEvent(QKeyEvent*) ()
#19 0x000000010048b8eb in QLineEdit::keyPressEvent(QKeyEvent*) ()
#20 0x00000001001056bd in QWidget::event(QEvent*) ()
#21 0x000000010048c18b in QLineEdit::event(QEvent*) ()
#22 0x000000010043d9f0 in QAbstractSpinBox::keyPressEvent(QKeyEvent*) ()
#23 0x00000001001056bd in QWidget::event(QEvent*) ()
#24 0x000000010043bb1b in QAbstractSpinBox::event(QEvent*) ()
#25 0x00000001004d7be5 in QSpinBox::event(QEvent*) ()
#26 0x00000001000a9e8d in QApplicationPrivate::notify_helper(QObject*, QEvent*) ()
#27 0x00000001000b198b in QApplication::notify(QObject*, QEvent*) ()
#28 0x0000000100d0321c in QCoreApplication::notifyInternal(QObject*, QEvent*) ()
#29 0x00000001000a9f2c in qt_sendSpontaneousEvent(QObject*, QEvent*) ()
#30 0x0000000100125cc1 in QKeyMapper::sendKeyEvent(QWidget*, bool, QEvent::Type, int, QFlags<Qt::KeyboardModifier>, QString const&, bool, int, unsigned int, unsigned int, unsigned int, bool*) ()
#31 0x0000000100126b43 in QKeyMapperPrivate::translateKeyEvent(QWidget*, OpaqueEventHandlerCallRef*, OpaqueEventRef*, void*, bool) ()
#32 0x000000010006072e in qt_dispatchKeyEvent(void*, QWidget*) ()
#33 0x000000010005478b in -[QCocoaView keyDown:] ()
#34 0x00007fff815a90c7 in -[NSWindow sendEvent:] ()
#35 0x0000000100059891 in -[QCocoaWindow sendEvent:] ()
#36 0x00007fff814ddafa in -[NSApplication sendEvent:] ()
#37 0x000000010005cf0a in -[QNSApplication sendEvent:] ()
#38 0x00007fff814746de in -[NSApplication run] ()
#39 0x0000000100066c04 in QEventDispatcherMac::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
#40 0x0000000100def774 in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
#41 0x0000000100defa94 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) ()
#42 0x0000000100df10bc in QCoreApplication::exec() ()
#43 0x0000000100001cf6 in main ()
  • rect 是 QWidget 的成员函数:如果在对象完全构造之前调用它可能会崩溃。您何时尝试调用该函数?
  • 它是在构造 PlotCanvas 对象之后,实际上是在 PlotCanvas 对象外部调用的公共成员函数内部调用的。还可以注意到在构造函数中没有调用 getDivCount()。
  • 您能否显示构造对象的代码以及调用函数的位置?你说它驻留在另一个类中,但该类的构造函数没有初始化它……
  • 我已将代码添加到原始帖子中。两者都在 Board 类中初始化。它作为 QAbstractScrollArea 的视口存在。
  • 很好…但是您仍然没有显示 getDivCount 被调用的位置。
  • 它由 Board 类通过它的 getDivCount() 方法调用。这个 Board\\ 的 getDivCount() 在 spinbox 值改变时被另一个类调用。但我认为如何调用它并不重要。
  • 从堆栈跟踪中,您应该已经向我们展示了函数 Board::getDivCount() 和 CommonKnobs::updateScaleByBeginEnd() 的代码。


我已经整理好了,它使用 parent() 作为指向 Board 的指针(使用 scatic_cast 进行投射,我认为使用 static_cast 投射到错误的对象会在那时杀死它,但不是)来自 PlotCanvas 和我的另一个类使用,当实际上 parent() 在 PlotCanvas 和 QGroupBox 的情况下引用到 PlotCanvasScrollArea 时,在其他类的情况下。
奇怪的是,调试器显示我实际上跳入了 Board\\ 的代码,即使认为被调用对象的地址完全错误,更奇怪的是它在 PlotCanvas 代码中崩溃而不是原始代码(Board\\ 的代码)。
但现在没事了。谢谢各位:)


尝试使用小部件 geometry 而不是 rect。还要小心复制构造函数。如果您使用成员变量,则需要使用 setGeometry 或 setRect 而不是复制构造函数。

请参阅 Qt 窗口几何文档。


您的 scrollArea 是作为 plotSplitter 的子级创建的,但它永远不会使用 addWidget() 添加到拆分器中,此外 plotSplitter 没有父级,这意味着它将是它自己的窗口。我想问题可能出在您将 scrollArea 的视口设置为 plotsCanvas 时,这是另一个没有父级的 QWidget,因此也没有自己的窗口。

尝试这样的事情并从那里开始工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Board(QString & name) : name(name)
{
    hbox = new QHBoxLayout();
    commonKnobGroup = new QGroupBox(“Common settings:”);
    commonKnobGroup>setMinimumWidth(190);
    commonKnobGroup>setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
    commonKnobs = new CommonKnobs(commonKnobGroup);
    hsplitter = new QSplitter();
    plotGroupBox = new QGroupBox(“Measurement plots:”, hsplitter);
    settingsGroupBox = new QGroupBox(“Plot settings:”, hsplitter);
    plotSplitter = new QSplitter(this);
    plotHbox = new QHBoxLayout();
    plotHbox>addWidget(plotSplitter);
    plotGroupBox>setLayout(plotHbox);
    settingsVLayout = new QVBoxLayout();
    plotNamesColumn = new QListWidget(plotSplitter);
    scrollArea = new PlotCanvasScrollArea(plotSplitter);
    plotSplitter>addWidget(plotNamesColumn);
    plotSplitter>addWidget(scrollArea);
    //scrollArea->setWidgetResizable(true);
    plotsCanvas = new PlotCanvas(this);
    scrollArea>setViewport(plotsCanvas);
    scrollArea>setBackgroundRole(QPalette::Dark);
    specializedKnobGroup = new QGroupBox(“Probe settings:”);
    plotSettings = new QStackedWidget(specializedKnobGroup);
    settingsVLayout>addWidget(commonKnobGroup);
    settingsVLayout>addWidget(specializedKnobGroup);
    settingsGroupBox>setLayout(settingsVLayout);
    hbox>addWidget(hsplitter);
    setLayout(hbox);
    connect(plotNamesColumn, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), this,
            SLOT(changePageNames(QListWidgetItem*, QListWidgetItem*)));
    connect(commonKnobs, SIGNAL(scaleUpdated()), plotsCanvas, SLOT(update()));

};

  • 它考虑过了,但我无法想象它会改变它,因为visuall GUI看起来一样 – 所以小部件的层次结构必须是相同的。但是感谢您指出这一点,我认为只是使某些东西成为父对象等于 addWidget 调用该父对象,反之亦然。我试过这段代码,但结果是一样的:(..我开始认为我已经破坏了Qt或其他东西……
  • 您是否也尝试向 hsplitter 添加父级?如 hsplitter = new QSplitter(this);这是一条我会走的路,因为我能想到的唯一原因是 rect() 出于某种原因返回零,而 getDivCount() 正在除以零。因此,零尺寸可能与您的布局和小部件父级等有关。
  • 还有两件事要检查:1)您是否混合了调试库和发布库?这可能会导致非常奇怪的错误。 2) 在代码的其他地方寻找缓冲区溢出。可能是这个错误在其他地方,而这个调用恰好在内存中遇到了一个坏点。
  • 我如何检查库的混合?我正在使用 Xcode 设置库查找路径到 QtSDK/Desktop/Qt/474/gcc/include 和 QtSDK/Desktop/Qt/474/gcc/lib/** 并且我已经添加了框架 QtGui.framework 和 QtCore.framework 到项目框架所以我真的不控制使用哪些库..
  • 我在文档中找到了这个:”首先,我们在布局中创建我们想要的小部件。然后,我们创建 QHBoxLayout 对象并将小部件添加到布局中。最后,我们调用 QWidget::setLayout() 来安装QHBoxLayout 对象到小部件上。此时,布局中的小部件被重新设置为将窗口作为其父级。”所以我明白当我将小部件添加到布局时,我不需要声明那里的父级,只要我使用 setLayout() 安装布局…



查看崩溃堆栈跟踪 – 它是否会导致某个地方的构造函数?我的第一个想法是,我不确定您是否应该在构造函数中调用 update – 我可能不在基地,但这对我来说似乎是错误的。如果 update 应该在 QWidget 构造函数中调用,那么基本构造函数将调用它(使您的调用变得多余),如果不应该,那么我完全不清楚会发生什么。

  • 事实并非如此,因为小部件显示正确,它在执行一些调用 getDivCount() 方法的 gui 操作后崩溃。但是为了安心,我已将其注释掉,但它仍然存在段错误。


来源:https://www.codenong.com/11371020/

微信公众号
手机浏览(小程序)

Warning: get_headers(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57

Warning: get_headers(): Failed to enable crypto in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57

Warning: get_headers(https://static.shanhubei.com/qrcode/qrcode_viewid_9870.jpg): failed to open stream: operation failed in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57
0
分享到:
没有账号? 忘记密码?