Ошибка клонирования Qt QString - PullRequest
1 голос
/ 07 декабря 2009

Я создаю свое первое приложение Qt с использованием Qt Creator, и все шло хорошо, пока я не начал получать странный SIGSEGV с линии, явно безвредной.

Это ошибка:

Программа получила сигнал SIGSEGV, Ошибка сегментации. 0x0804e2fe в QBasicAtomicInt :: ref (this = 0x0) по адресу /usr/lib/qt/include/QtCore/qatomic_i386.h:120

Возвращая исключение на gdb , я обнаружил, что простой метод получения передает нулевой указатель на конструктор клона, когда я возвращаю свой атрибут.

Вывод обратной трассировки:

(gdb) backtrace
#0 0x0804e2fe in QBasicAtomicInt::ref (this=0x0) at /usr/lib/qt/include/QtCore/qatomic_i386.h:120
#1 0x0804eb1b in QString (this=0xbfcc8e48, other=@0xbfcc8e80) at /usr/lib/qt/include/QtCore/qstring.h:712
#2 0x0805715e in Disciplina::getId (this=0xbfcc8e7c) at disciplina.cpp:13
[...]

Проверка указателя, переданного конструктору QString:

(gdb) x 0xbfcc8e80
0xbfcc8e80: 0x00000000

И это - дисциплина.cpp: 13

QString Disciplina::getId()
{
    return id;
}

Итак, все указывает на конструктор копирования QString, получая пустой указатель, что не имеет смысла для меня. id был объявлен как закрытая строка QString.

private:
    QString id;

Ну, я понятия не имею, что может происходить, и мои навыки отладки зашли так далеко, что если бы кто-нибудь смог выдвинуть идею, я был бы очень рад.

Спасибо.

редактировать

Дополнительный код по запросу.

disciplina.h

#ifndef DISCIPLINA_H
#define DISCIPLINA_H
#include <QString>
#include <QMap>
#include "curso.h"
#include "turma.h"

class Curso;

class Turma;

class Disciplina
{
private:
    unsigned short int serie;
    QString id;
    QString nome;
    Curso* curso;
    QMap<unsigned int, Turma*> turmas;    
public:
    Disciplina(QString id, Curso* curso, QString nome, unsigned short int serie);

    QString getId();
    const Curso getCurso();
    QString getNome();
    void setNome(QString nome);
    void addTurma(Turma* t, unsigned int id);
    QMap<unsigned int, Turma*> getTurmas();
};

#endif // DISCIPLINA_H

disciplina.cpp

#include "disciplina.h"

Disciplina::Disciplina(QString id, Curso* curso, QString nome, unsigned short int serie)
{
    this->id = id;
    this->curso = curso;
    this->nome = nome;
    this->serie = serie;
}

QString Disciplina::getId()
{
    return id;
}

const Curso Disciplina::getCurso()
{
    const Curso c(*this->curso);
    return c;
}

QString Disciplina::getNome()
{
    return this->nome;
}

void Disciplina::setNome(QString nome)
{
    this->nome = nome;
}

void Disciplina::addTurma(Turma* t, unsigned int id)
{
    this->turmas.insert(id, t);
}

QMap<unsigned int, Turma*> Disciplina::getTurmas()
{
    return this->turmas;
}

Функция вызова (я сломал ее для упрощения отладки)

Disciplina*
MainWindow::getSelectedDisciplina()
{
    if(ui->disciplinaTurma->count() > 0 && currentCurso)
    {
        QMap<QString, Disciplina*> qm(currentCurso->getDisciplinas());
        QString key = ui->disciplinaTurma->itemText(ui->disciplinaTurma->currentIndex());
        Disciplina* d = qm[key];
        QMessageBox::information(this, d->getId(), d->getNome());
        return d;
    }
    else
        return NULL;
}

решаемые

Объект Disciplina, вставленный в карту, выходит из области видимости и поэтому удаляется. Поскольку, как указал Джасинто, при создании доступа к несуществующему ключу Map создавала ванильное значение, похоже, объект был там.

Спасибо вам обоим Jacinto и sth за помощь.

Ответы [ 2 ]

5 голосов
/ 07 декабря 2009

На карте c ++, если элемент не существует, когда вы пытаетесь получить к нему доступ по его ключу, он просто создает его для вас. Вы пытаетесь сделать то же самое здесь, и если QMap работает так же, это и является причиной вашего segfault.

Что вам нужно сделать, это проверить наличие ключа на карте перед тем, как получить к нему доступ.

edit: для пуристов C ++, пожалуйста, дайте мне знать, если у меня есть это право. Я знаю, что на практике безопаснее тестировать, прежде чем получить к нему доступ, но я не знаю, является ли фраза «он создает один для вас» очень хорошим способом выразить это. Это может просто вернуть вам место в памяти, где будет такое значение; Я не знаю, будет ли он вызывать конструктор по умолчанию.

2 голосов
/ 07 декабря 2009

Возможно, объект Disciplina, который вы вызываете getId(), был ранее удален, так что он больше не действителен.

...