Qt QString のクローン作成セグメンテーション フォールト
質問
私は Qt Creator を使用して最初の Qt アプリを構築していますが、一見無害な行から奇妙な SIGSEGV を取得し始めるまではすべてが順調でした。
これがエラーです:
プログラムは信号 SIGSEGV、セグメンテーション違反を受信しました。/usr/lib/qt/include/QtCore/qatomic_i386.h:120 の QBasicAtomicInt::ref (this=0x0) の 0x0804e2fe
例外をバックトレースすることで、 gdb, 属性を返すときに、単純なゲッターがクローン コンストラクターに NULL ポインターを渡していることがわかりました。
バックトレース出力:
(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) × 0xbfcc8e80
0xbfcc8e80:0x00000000
そしてこれは disciplina.cpp:13
QString Disciplina::getId()
{
return id;
}
したがって、すべては空のポインターを受け取る QString のコピー コンストラクターを指していますが、これは私にとって意味がありません。 ID プライベート QString として宣言されました。
private:
QString id;
そうですね、私には何が起こっているのか見当もつきませんし、私のデバッグスキルもこれまでしかありません。そのため、誰かがアイデアを投げてくれたら、本当にうれしいです。
ありがとう。
編集
リクエストに応じてさらにコードを追加します。
しつけ.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
ディシプリナ.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 はバニラ値を作成するため、オブジェクトがそこにあるように見えました。
あなたがた両方に感謝します ハシント そして sth あなたの助けに。
解決
C++ のマップでは、キーによって要素にアクセスしようとしたときに要素が存在しない場合、要素が作成されるだけです。ここで同じことをしようとしていますが、QMap が同じように動作する場合、これがセグメンテーション違反の原因です。
行う必要があるのは、マップにアクセスする前に、マップ内にキーが存在するかどうかをテストすることです。
編集:C++ の純粋主義者の方は、私が正しいかどうか教えてください。実際には、アクセスする前にテストした方が安全であることはわかっていますが、「自動的に作成される」という表現が適切かどうかはわかりません。そのような値が存在するメモリ内のスペースを返すだけかもしれません。実際にデフォルトのコンストラクターを呼び出すかどうかはわかりません。
他のヒント
たぶん、 Disciplina
呼び出しているオブジェクト getId()
on は以前に削除されたため、もう有効ではありません。