1

I'm a little new to object oriented programming, and very new to Qt and GUIs in general. I am now playing with this example in Nokia's Qt tutorial: http://doc.qt.nokia.com/4.1/tutorial-t5.html

I tried to extend the code; this is what I have now:

#include <QApplication>
#include <QFont>
#include <QLCDNumber>
#include <QPushButton>
#include <QSlider>
#include <QVBoxLayout>
#include <QWidget>

class MyWidget : public QWidget
{
public:
    MyWidget(QWidget *parent = 0);
};

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
{
    QPushButton *quit = new QPushButton(tr("Quit"));
    move(1600,0);
    quit->setFont(QFont("Times", 18, QFont::Bold));

    QPushButton* numbase;
    numbase = new QPushButton[4];
    numbase[0].setText("Dec");
    (numbase+1)->setText("Bin"); // Hihihi
    numbase[2].setText("Hex");
    numbase[3].setText("Oct");

    // a[i] == *(a+i)

    QLCDNumber *lcd = new QLCDNumber(8);
    lcd->setSegmentStyle(QLCDNumber::Filled);
    lcd->setMode(QLCDNumber::Hex);

    QSlider *slider = new QSlider(Qt::Horizontal);
    slider->setRange(0, 99);
    slider->setValue(0);

    connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
    connect(slider, SIGNAL(valueChanged(int)),
            lcd, SLOT(display(int)));

    connect(numbase+0, SIGNAL(clicked()), lcd, SLOT(setDecMode()));
    connect(numbase+1, SIGNAL(clicked()), lcd, SLOT(setBinMode()));
    connect(numbase+2, SIGNAL(clicked()), lcd, SLOT(setHexMode()));
    connect(numbase+3, SIGNAL(clicked()), lcd, SLOT(setOctMode()));

    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(quit);
    layout->addWidget(lcd);
    layout->addWidget(slider);

    // Segmentation fault if I include those two lines:
    for(int i=0;i<4;i++)
        layout->addWidget(numbase+i);
    // -------------

    setLayout(layout);
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MyWidget widget;
    widget.show();
    return app.exec();
}

When I include the marked two lines, the program does its job correctly, but if I quit it (and only then) the console shows a "Segmentation fault". I'd like to know why that happens.

And also, is there a better way to reference the 4 widgets? (numbase+2) looks weird, is this really how I am supposed to do this?

P Shved
  • 96,026
  • 17
  • 121
  • 165
Alexander Engelhardt
  • 1,632
  • 3
  • 16
  • 31
  • 2
    You might want to consider changing your picture, someone's already flagged this post as offensive, and I can't see anything offensive in the post so I assume it's the picture. – Hans Olsson Oct 17 '10 at 13:07
  • I find the picture quite nice, and can't imagine that a beautiful naked woman could actually offend anyone. But the majority of stackers won't agree with me, unfortunately. – P Shved Oct 17 '10 at 13:13
  • Wait, apparently I had this gravatar thing before. I did not use it on a coding site, though :) I changed the picture. – Alexander Engelhardt Oct 17 '10 at 13:19
  • what was the pic? I missed it. –  Oct 18 '10 at 11:45
  • @Will: just a naked lady (well, the top half of her). I already deleted it, so I can't show you anymore. – Alexander Engelhardt Oct 18 '10 at 12:33

3 Answers3

3

The possible reason of crash is that Qt, at deletion of the form, calls delete function for each widget on the form. So, at program exit, when destroying your form, Qt internals would execute the following sequence:

delete numbase[0];
delete numbase[1];
delete numbase[2];
delete numbase[3];

However, the correct way to free the memory would be

delete [] numbase;

because you allocated numbase with a special array allocation new[] operator, which is different from the usual new. And it's "undefined behavior" if you use delete instead of delete[] in C++. So, segmentation fault could happen if it's the case.

You can check if it's the reason, by allocating each emenent in your array separately, with new QPushButton;, as specified in the other answer.

Community
  • 1
  • 1
P Shved
  • 96,026
  • 17
  • 121
  • 165
  • Thanks! Where would I enter the delete[] line? – Alexander Engelhardt Oct 17 '10 at 12:53
  • @Alexx, it's not you who enters the `delete[]` line. It's internal Qt procedures which actually call `delete` operators (see my other answer http://stackoverflow.com/questions/3646300/why-cant-we-create-object-in-qt-without-the-new-keyword-i-e-on-stack/3646420#3646420 on this topic), and you can't change them. The best you could do is to allocate your objects in such a way that matches Qt's way of deallocating them. That means, not on stack, and not with `new[]` you used, but with causal `new` operator instead. – P Shved Oct 17 '10 at 12:56
  • I didn't know I walked on forbidden land :) I'll use pointer arrays from now on, thanks! – Alexander Engelhardt Oct 17 '10 at 13:00
2

A better way is to use a array of pointers, you should try it:

QPushButton *buttons[4];

buttons[0] = new QPushButton(this);
buttons[1] = new QPushButton(this);
buttons[2] = new QPushButton(this);
buttons[3] = new QPushButton(this);

buttons[0]->setText("foo")

connect(buttons[0], SIGNAL(clicked()), this, SLOT(bar()));
Dr. Snoopy
  • 55,122
  • 7
  • 121
  • 140
  • When will I finally grasp the pointers? :) Thanks. Array of pointers != pointer to array. I'll note that. – Alexander Engelhardt Oct 17 '10 at 12:54
  • Why is this -1? This is actually correct I was about to say the same. You need pointers in the array to use QPushButton as QWidget. – stribika Oct 17 '10 at 13:08
  • @Ankur: Yes. I'd like to know why exactly the segfault appears, though. – Alexander Engelhardt Oct 17 '10 at 13:11
  • I added the -1. Because OP asked why his code doesn't work, and this answer says nothing about this. Moreover, it forced Alexx into an accepting an incorrect conclusion that "Array of pointers != pointer to array" has *anything* to do with it. – P Shved Oct 17 '10 at 13:11
-1
  1. Try replacing 4 by 3 in the loop.

  2. If you want Qt to do garbage collection make sure you set the parent child relationship of widget correctly i.e. QPushButton resides in QWidget so set it in constructor.

  3. For simple UI like these try creating it using Qt Designer and see the generated code.

Ankur Gupta
  • 2,284
  • 4
  • 27
  • 40
  • I thought addWidget() takes care of the parent/child thing automatically. The other part of the code is from the Qt website, they didn't use it either. – Alexander Engelhardt Oct 17 '10 at 12:58
  • I am just letting you know about the best practices. Explicit is better than implicit. It's easy to read the code and see who is the parent of whom. – Ankur Gupta Oct 17 '10 at 13:06