Ошибка сегментации при попытке получить значение указателя в Qt - PullRequest
0 голосов
/ 03 октября 2011

Я довольно новичок в Qt и c ++, но совсем не новичок в программировании.У меня проблемы с использованием указателей в моей программе.В моем заголовочном файле у меня есть следующее назначение указателя закрытой переменной:

private:
    QString *currentFile;

В моей программе есть функция, которая начинается с копирования значения указателя currentFile в другую переменную QString:

QString fileName = *currentFile;

Однако это сразу вызывает ошибку сегментации при отладке.Я абсолютно не знаю, что я делаю неправильно.

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

*currentFile = QString::null;

Чтобы присвоить значение null значению указателя, однако это просто дало мне ошибку сегментациикак только конструктор был вызван.

Надеюсь, что кто-то может помочь.

Спасибо

РЕДАКТИРОВАТЬ

больше кода:

notepad.h:

class Notepad : public QMainWindow
{
    Q_OBJECT

public:
    Notepad();

private slots:
    void open();
    void save();
    void saveAs();
    void quit();

private:
    QTextEdit *textEdit;
    QString *currentFile;
    QString *currentContents;
};

функция, создающая ошибку (void save ()) в notepad.cpp:

void Notepad::save(){
    QString fileName = *currentFile;
    if(fileName != "")
    {
        QFile file(fileName);
        if(!file.open(QIODevice::WriteOnly))
        {
            QMessageBox::critical(this, tr("Error"), tr("Could not write to file"));
            return;
        }
        else
        {
            QTextStream stream(&file);
            QString editorContent = textEdit->toPlainText();
            currentContents = &editorContent;
            stream << editorContent;
            stream.flush();
            file.close();
        }
    }
    else
        saveAs();
}

Ответы [ 5 ]

2 голосов
/ 03 октября 2011

Нет причин использовать указатели в коде, который вы предоставили.Итак, попробуйте это вместо этого (из кода перед предоставлением правки)

private:
    QString currentFile;
QString fileName = currentFile;
currentFile = QString::null;
2 голосов
/ 03 октября 2011

В обоих случаях:

QString fileName = *currentFile;
*currentFile = QString::null;

вы разыменовываете унифицированный указатель.

2-е присваивание не инициализирует указатель на NULL;то, что он делает: сначала разыменовывает указатель currentFile и уничтожает объект, на который он указывает, и заменяет его объектом QString :: null.

QString :: null - это специальная структура, используемая Qt для обозначения неинициализированных строк, но не путайте ее с указателем NULL.

Вы должны инициализировать ваш указатель следующим образом:

currentFile = new QString();
2 голосов
/ 03 октября 2011

Скорее всего, это связано с тем, что вы никогда не выделяли хранилище для строки. Указатель просто хранит адрес памяти, и если его значение инициализируется равным 0 (или, что еще хуже, нулю и содержит полностью неопределенный адрес), то он не указывает на допустимый строковый объект и пытается использовать память, на которую он указывает строковый объект приводит к неопределенному поведению (в вашем случае к segfault).

Итак, сначала вам нужно выделить память для строки и создать строку, используя (вероятно, в конструкторе окружающего объекта):

currentFile = new QString;

и позже (когда больше не нужны, например, в деструкторе окружающего объекта):

delete currentFile;

Но, как сказано в комментариях, я действительно сомневаюсь, что вам нужен член-указатель. Почему бы просто не использовать объект QString в качестве члена. Или, если вам действительно нужны указатели, лучше используйте какой-нибудь умный указатель (например, auto_ptr или новый C ++ 11 unique_ptr или shared_ptr).

С QObject производными типами (виджетами и т. П.) Это другая история, и вам лучше использовать для них указатели (и Qt обрабатывает освобождение для вас, если используется правильно). Но QString - это (как обычно строки) довольно тип значения (похожий на встроенные типы), и в большинстве случаев нет необходимости выделять его динамически.

1 голос
/ 03 октября 2011

Если currentFile равен нулю, то, разумеется, при разыменовании происходит сбой Установка его в QString :: null не даст вам пустую строку. Это дает вам нулевой указатель. То, что вы хотите, это что-то вроде этого: currentFile = "";

Cat Plus также имеет хороший момент. Во-первых, вам не нужен указатель (для того, что вы нам показали).

0 голосов
/ 03 октября 2011

Поместите это currentFile = new QString(); в конструктор

РЕДАКТИРОВАТЬ:

и поместите delete currentFile; в деструктор

...