简体   繁体   English

Qt QString克隆分割错误

[英]Qt QString cloning Segmentation Fault

I'm building my first Qt app using Qt Creator, and everything was going fine until I started getting a strange SIGSEGV from a line apparently harmless. 我正在使用Qt Creator构建我的第一个Qt应用程序,并且一切都进行得很好,直到我开始从显然无害的生产线获得奇怪的SIGSEGV。

This is the error: 这是错误:

Program received signal SIGSEGV, Segmentation fault. 程序收到信号SIGSEGV,分段故障。 0x0804e2fe in QBasicAtomicInt::ref (this=0x0) at /usr/lib/qt/include/QtCore/qatomic_i386.h:120 /usr/lib/qt/include/QtCore/qatomic_i386.h:120处QBasicAtomicInt :: ref(this = 0x0)中的0x0804e2fe

By backtracing the exception on gdb , I found that a simple getter is passing a NULL pointer to the clone constructor when I return my attribute. 通过回溯gdb上的异常,我发现当我返回属性时,一个简单的getter会将NULL指针传递给克隆构造函数。

Backtrace output: 回溯输出:

(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
[...] [...]

Inspecting the pointer passed to the QString constructor: 检查传递给QString构造函数的指针:

(gdb) x 0xbfcc8e80 (gdb)x 0xbfcc8e80
0xbfcc8e80: 0x00000000 0xbfcc8e80:0x00000000

And this is disciplina.cpp:13 这是disciplina.cpp:13

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

So, all points towards the copy constructor of QString receiving an empty pointer, which makes no sense to me. 因此,所有指向QString的副本构造函数的对象都接收到一个空指针,这对我来说毫无意义。 id was declared as a private QString. id被声明为私有QString。

private:
    QString id;

Well, I have no clue of what could be going on, and my debugging skills only go so far, so if anyone could throw an idea I'd be really glad. 好吧,我对可能发生的事情一无所知,而且我的调试技能还很先进,所以如果有人可以提出一个想法,我将非常高兴。

Thanks. 谢谢。

edit 编辑

More code, as requested. 根据要求提供更多代码。

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 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;
}

Caller function (I broke it down for easier debugging) 调用者函数(为方便调试,我对其进行了细分)

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;
}

Solved 解决了

The Disciplina object inserted into the map was getting out of scope and therefore deleted. 插入到地图中的Disciplina对象超出范围,因此已删除。 Since, as Jacinto pointed out, Map created a vanilla value when you try to access a nonexistent key, it looked like the object was there. 正如Jacinto所指出的,由于当您尝试访问不存在的键时,Map创建了一个普通值,因此看起来该对象在那里。

Thank you both Jacinto and sth for your help. 谢谢Jacintosth的帮助。

In c++'s map, if the element doesn't exist when you try to access it by its key, it just creates one for you. 在c ++的映射中,如果在尝试通过键访问该元素时不存在该元素,则它只会为您创建一个。 You are attempting to do the same thing here, and if QMap works the same way, this is what is causing your segfault. 您正在尝试在此处执行相同的操作,并且如果QMap以相同的方式工作,这就是导致段错误的原因。

What you should be doing is testing for the key's presence in the map before accessing it. 您应该做的是在访问密钥之前在地图中测试密钥的存在。

edit: for the C++ purists, please let me know if i have that right. 编辑:对于C ++纯粹主义者,请让我知道我是否有这个权利。 I know in practice it's safer to test before accessing it, but I don't know if the phraseology of "it creates one for you" is a very good way to put it. 我知道实际上在访问它之前进行测试是比较安全的,但是我不知道“为您创建一个”的说法是否是一种很好的表达方式。 It might just return you the space in memory where such a value would be; 它可能只是向您返回该值所在的内存空间。 I don't know if it would actually call the default constructor. 我不知道它是否会真正调用默认构造函数。

也许您正在调用getId()Disciplina对象先前已被删除,因此它不再有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM