Qt QString克隆分段错误

Gab*_*ini 1 c++ qstring qt pointers

我正在使用Qt Creator构建我的第一个Qt应用程序,一切都很顺利,直到我从一条明显无害的线路开始得到一个奇怪的SIGSEGV.

这是错误:

程序接收信号SIGSEGV,分段故障.QBasicAtomicInt :: ref(this = 0x0)中的0x0804e2fe位于/usr/lib/qt/include/QtCore/qatomic_i386.h:120

通过在gdb上回溯异常,我发现当我返回属性时,一个简单的getter将NULL指针传递给克隆构造函数.

Backtrace输出:

(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

这是门徒.13:13

QString Disciplina::getId()
{
    return id;
}
Run Code Online (Sandbox Code Playgroud)

所以,所有指向QString的复制构造函数的点都接收到一个空指针,这对我来说毫无意义.id被声明为私有QString.

private:
    QString id;
Run Code Online (Sandbox Code Playgroud)

好吧,我不知道会发生什么,而且我的调试技巧只能到目前为止,所以如果有人可以提出一个想法我真的很高兴.

谢谢.

编辑

根据要求提供更多代码.

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
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

来电功能(为了便于调试,我把它分解了)

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;
}
Run Code Online (Sandbox Code Playgroud)

解决了

Disciplina插入到地图中的对象超出了范围,因此被删除.因为正如Jacinto所指出的那样,当你试图访问一个不存在的密钥时,Map创建了一个vanilla值,它看起来就像那个对象.

感谢Jacinto某人的帮助.

San*_*nto 5

在c ++的map中,如果当你试图通过它的键访问它时该元素不存在,它只会为你创建一个元素.你试图在这里做同样的事情,如果QMap以相同的方式工作,这就是导致你的段错误的原因.

您应该做的是在访问密钥之前测试密钥在地图中的存在.

编辑:对于C++纯粹主义者,如果我有这个权利,请告诉我.我知道在实践中,在访问它之前测试更安全,但我不知道"它为你创建一个"这句话是否是一种非常好的方式.它可能只会返回内存中存在这样一个值的空间; 我不知道它是否会实际调用默认构造函数.