Почему возникает ошибка ошибки сегментации, если я включаю массив виджетов в Qt? - PullRequest
1 голос
/ 17 октября 2010

Я немного новичок в объектно-ориентированном программировании и очень плохо знаком с Qt и GUI в целом.Сейчас я играю с этим примером в руководстве по Qt от Nokia: http://doc.qt.nokia.com/4.1/tutorial-t5.html

Я попытался расширить код;вот что у меня сейчас:

#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();
}

Когда я добавляю отмеченные две строки, программа выполняет свою работу правильно, но если я выйду из нее (и только тогда), консоль выдаст сообщение «Ошибка сегментации».Я хотел бы знать, почему это происходит.

А также, есть ли лучший способ ссылки на 4 виджета?(numbase+2) выглядит странно, это правда, как я должен это сделать?

Ответы [ 3 ]

3 голосов
/ 17 октября 2010

Возможная причина сбоя в том, что Qt при удалении формы вызывает функцию delete для каждого виджета на форме. Таким образом, при выходе из программы, при уничтожении вашей формы, внутренняя структура Qt будет выполнять следующую последовательность:

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

Однако правильный способ освобождения памяти будет

delete [] numbase;

потому что вы выделили numbase с помощью специального оператора выделения массива new[], который отличается от обычного new. И это «неопределенное поведение», если вы используете delete вместо delete[] в C ++. Таким образом, ошибка сегментации может произойти, если это так.

Вы можете проверить, является ли это причиной, выделив каждый компонент в вашем массиве отдельно, с помощью new QPushButton;, как указано в другой ответ .

2 голосов
/ 17 октября 2010

Лучше использовать массив указателей, попробуйте:

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()));
0 голосов
/ 17 октября 2010
  1. Попробуйте заменить 4 на 3 в цикле.

  2. Если вы хотите, чтобы Qt выполнял сборку мусора, убедитесь, что вы правильно установили отношения родитель-потомок виджета, т.е. QPushButton находится в QWidget, поэтому установите его в конструкторе.

  3. Для такого простого пользовательского интерфейса попробуйте создать его с помощью Qt Designer и увидеть сгенерированный код.

...