Qt QString克隆分段错误
我正在使用 Qt Creator 构建我的第一个 Qt 应用程序,一切都很顺利,直到我开始从一条显然无害的线路中收到一个奇怪的 SIGSEGV。
这是错误:
程序收到信号 SIGSEGV,分段错误。 0x0804e2fe 在 QBasicAtomicInt::ref (this=0x0) 位于 /usr/lib/qt/include/QtCore/qatomic_i386.h:120
通过回溯 gdb 上的异常,我发现一个简单的 getter 正在传递当我返回属性时,指向克隆构造函数的 NULL 指针。
回溯输出:
(gdb) 回溯
#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
这是disciplina.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
对象进入地图超出了范围,因此被删除。正如 Jacinto 指出的那样,因为当您尝试访问不存在的键时,Map 创建了一个普通值,所以看起来该对象就在那里。
感谢Jacinto和sth的帮助。
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.
This is the error:
Program received signal SIGSEGV, Segmentation fault.
0x0804e2fe in QBasicAtomicInt::ref (this=0x0) at /usr/lib/qt/include/QtCore/qatomic_i386.h:120
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.
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:
(gdb) x 0xbfcc8e80
0xbfcc8e80: 0x00000000
And this is 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. id was declared as a private 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
#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. 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.
Thank you both Jacinto and sth for your help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在 C++ 的映射中,如果当您尝试通过其键访问该元素时该元素不存在,它只会为您创建一个。您尝试在这里做同样的事情,如果 QMap 以相同的方式工作,这就是导致您的段错误的原因。
您应该做的是在访问密钥之前测试该密钥是否存在于地图中。
编辑:对于 C++ 纯粹主义者,请告诉我我是否有权利。我知道实际上在访问它之前进行测试更安全,但我不知道“它为您创建一个”这句话是否是一种很好的表达方式。它可能只是返回内存中此类值所在的空间;我不知道它是否真的会调用默认构造函数。
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. You are attempting to do the same thing here, and if QMap works the same way, this is what is causing your segfault.
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. 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
对象之前已被删除,因此它不再有效。Maybe the
Disciplina
object you are callinggetId()
on was previously deleted, so that it is not valid anymore.