Ошибка сегментации вектора C ++ вызывает сбой, если вызывается вектор - PullRequest
0 голосов
/ 30 мая 2018

ОБНОВЛЕННЫЙ ВОПРОС:

Эй,

Я новичок и действительно не разбираюсь в кодировании, но у нас в университете была задача, где я столкнулся с проблемой, которую сам не смог решить.В одном классе вектор вызывает проблему, которую я не понимаю.После нескольких часов проб и ошибок я немного устал от догадок ... Итак, я пробую это здесь и надеюсь на некоторую помощь.

Предполагается, что программа нарисует диаграмму на основе некоторых входных переменных, которые пользователь может изменить.На данный момент я пытаюсь реализовать рисование графика.Ввод и расчет данных работает.Одним из аспектов задачи является то, что мы должны сохранить вычисленные данные в векторе и передать этот вектор в качестве указателя на другие функции, например, рисовальщику.Теперь проблема возникает.Любое взаимодействие с вектором m_punkte, которое я передал paintEvent, вызывает сбой программы.Я мог бы сузить проблему до таких команд, как: vector-> begin () или vector-> end ().В тот момент, когда программа пытается выполнить их, Windows останавливает программу.Сначала я думал, что вектор может быть каким-то образом передан неправильно, и я пытаюсь вызвать пустой вектор, или адрес не определен, но даже такие команды, как vector-> emty (), вызывают сбой.Поэтому я верю, что это более общая ошибка, вызванная рамками или чем-то в этом роде.После запуска инструмента отладки он также дал понять, что ошибка вызвана упомянутыми командами, и еще больше сообщил мне следующее:

Der Prozess wurde wegen eines Signals vom Betriebssystem angehalten.
Name desСигналы: SIGSEGV
Bedeutung: Ошибка сегментации

Я полагаю, это какая-то проблема с памятью, верно?

Я был бы очень рад, если бы кто-то мог мне помочь, поэтому я могуснова поработайте над реальной задачей, не догадываясь, почему этот вектор каким-то образом нарушен:)

Что я также могу сказать, так это то, что я работаю с Qt Creator и программа работает как программа QtWidget, если это помогает.

Ссылка Dropbox на копию программы: https://www.dropbox.com/sh/l5e220lk5y7jx2z/AAAdG7AjHiiKJxOKWT-zrP8ia?dl=0

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

datenpunkt.h

#ifndef DATENPUNKT_H
#define DATENPUNKT_H

#include <vector>

struct datenpunkt
{
        float temperatur;
        float widerstand;
        float laenge;
};
typedef std::vector<datenpunkt> PunktVektor;

#endif // DATENPUNKT_H

diagrammwidget.h

#ifndef DIAGRAMMWIDGET_H
#define DIAGRAMMWIDGET_H

#include "datenpunkt.h"
#include <QWidget>

namespace Ui {
class DiagrammWidget;
}

class DiagrammWidget : public QWidget
{
    Q_OBJECT

public:
    explicit DiagrammWidget( QWidget *parent = 0);
    ~DiagrammWidget();

    void setPunkte (PunktVektor *punkte);

    void setUntere_temp(int untere_temp);
    void setObere_temp(int obere_temp);
    void setAufloesung(int aufloesung);

    PunktVektor *punkte() const;

protected:
    void paintEvent(QPaintEvent *event);

private:
    Ui::DiagrammWidget *ui;
    PunktVektor *m_punkte;

    int m_untere_temp = 0;
    int m_obere_temp = 0;
    int m_aufloesung = 0;
};

#endif // DIAGRAMMWIDGET_H

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include "datenpunkt.h"

#include <string.h>
#include <QDialog>
#include <QString>

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

    void werteberechnung(PunktVektor *m_PunktListe);

    float untere_temp() const;
    void setUntere_temp(float untere_temp);

    float obere_temp() const;
    void setObere_temp(float obere_temp);

    int aufloesung() const;
    void setAufloesung(int aufloesung);

    QString werkstoff() const;
    void setWerkstoff(QString werkstoff);

    float materialkonstante() const;
    void setMaterialkonstante(float materialkonstante);

    float bezugswiderstand() const;
    void setBezugswiderstand(float bezugswiderstand);

    float wiederstand() const;
    void setWiederstand(float wiederstand);

    float temperatur() const;
    void setTemperatur(float temperatur);

private slots:
    void on_speichern_clicked();
    void on_verwerfen_clicked();
    void on_zuruecksetzen_clicked();

private:
    Ui::Dialog *ui;
    PunktVektor *m_PunktListe;

    QString m_werkstoff = "A 34-2/30 (SIEMENS)";
    float m_materialkonstante = 3440;               // B/ K
    float m_bezugswiderstand = 5000;                // Rto/ Ohm
    float m_untere_temp = 0 + 272.15;
    float m_obere_temp = 300 + 272.15;
    int m_aufloesung = 10;

    float m_RT= 0;                            // Rt/ Ohm
    float m_To = 20 + 272.15;
    float m_T = 0;                             // T/ C°
    float m_UD;         //Untere Dekadengrenze
    float m_OD;         //Obere Dekadengrenze

};

#endif // DIALOG_H

diagrammwidget.cpp

#include "diagrammwidget.h"
#include "ui_diagrammwidget.h"
#include "datenpunkt.h"

#include <vector>
#include <QtCore>
#include <QtGui>

DiagrammWidget::DiagrammWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::DiagrammWidget){
    ui->setupUi(this);
    m_punkte = 0;
}
DiagrammWidget::~DiagrammWidget(){
    delete ui;
}
void DiagrammWidget::setPunkte(PunktVektor *punkte){
    m_punkte = punkte;
}
void DiagrammWidget::paintEvent(QPaintEvent *event)
{
    QPainter myPainter (this);
    /*if((m_punkte == 0|| m_punkte->size() == 0)){
        myPainter.drawText(100,100,"No Points found!");
        return;
    }*/
    datenpunkt ersterPunkt=*m_punkte->begin();
    datenpunkt startPunkt = ersterPunkt;
    PunktVektor::iterator it;
    for( it = m_punkte->begin()++; it != m_punkte->end(); it++){
        datenpunkt p = *it;


        myPainter.drawLine(startPunkt.temperatur,startPunkt.laenge,                 
        p.temperatur,p.laenge);
        startPunkt = p;
        }
    }
    PunktVektor *DiagrammWidget::punkte() const{
        return m_punkte;
    }
    void DiagrammWidget::setAufloesung(int aufloesung){
        m_aufloesung = aufloesung;
    }
    void DiagrammWidget::setObere_temp(int obere_temp){
        m_obere_temp = obere_temp;
    }
    void DiagrammWidget::setUntere_temp(int untere_temp){
        m_untere_temp = untere_temp;
    }

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"
#include "datenpunkt.h"
#include "diagrammwidget.h"

#include <QtCore>
#include <QtGui>
#include <QString>
#include <math.h>

#include <iostream>
using namespace std;

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    m_PunktListe = new PunktVektor;

    //Standarteinstellungen
    ui->werkstoff->setText("A 34-2/30 (SIEMENS)");
    ui->materialkonstante->setValue(3440);
    ui->materialkonstante->setSuffix(" K");
    ui->bezugswiderstand->setValue(5000);
    ui->bezugswiderstand->setSuffix(" Ω");
    ui->unteretemperatur->setValue(0);
    ui->unteretemperatur->setSuffix(" °C");
    ui->oberetemperatur->setValue(300);
    ui->oberetemperatur->setSuffix(" °C");
    ui->aufloesung->setValue(10);
    ui->aufloesung->setSuffix(" Δ°C");

    ui->unteretemperatur->setMaximum(ui->oberetemperatur->value());
    ui->oberetemperatur->setMinimum(ui->unteretemperatur->value());
    ui->unteretemperatur->setSingleStep(ui->aufloesung->value());
    ui->oberetemperatur->setSingleStep(ui->aufloesung->value());

    werteberechnung(m_PunktListe);

    //Diagramm aktualisieren und Anzeigen
    DiagrammWidget dg;
    dg.setUntere_temp(m_untere_temp);
    dg.setObere_temp(m_obere_temp);
    dg.setAufloesung(m_aufloesung);
    dg.setPunkte(m_PunktListe);
    dg.show();
}

Dialog::~Dialog()
{
    delete m_PunktListe;
    delete ui;
}

void Dialog::werteberechnung(PunktVektor *m_PunktListe)
{
    datenpunkt p;
    float temp = m_untere_temp;

    //Anzahl der zu bestimmenden Datenpunkte
    int anzahl = (m_obere_temp-m_untere_temp)/m_aufloesung;

    //Bestimmen der Dekadengrenzen UD und OD
    m_RT = m_bezugswiderstand * pow(M_E, (m_materialkonstante*         
((1/m_obere_temp)-(1/m_To))));
    m_UD = (int(log10(m_RT)));
    m_RT = m_bezugswiderstand * pow(M_E, (m_materialkonstante*     
((1/m_untere_temp)-(1/m_To))));
    m_OD = (int(log10(m_RT))+1);

    //Füllen des Datenvectors
    for (int i = 0; i <= anzahl; i++){
        m_RT = m_bezugswiderstand * pow(M_E, (m_materialkonstante* 
((1/temp)-(1/m_To))));
        p.widerstand = m_RT;
        p.temperatur = temp;
        float x = log10(m_RT);
        if(m_UD != 0){
            p.laenge = ((x-m_UD)*5);
        }
        else
            p.laenge = x*5;

        m_PunktListe->push_back(p);
        temp = temp + m_aufloesung;
    }
}

void Dialog::on_speichern_clicked()
{
    setWerkstoff(ui->werkstoff->text());
    setMaterialkonstante(ui->materialkonstante->value());
    setBezugswiderstand(ui->bezugswiderstand->value());
    setUntere_temp(ui->unteretemperatur->value()+ 272.15);
    setObere_temp(ui->oberetemperatur->value()+ 272.15);
    setAufloesung(ui->aufloesung->value());

    ui->unteretemperatur->setMaximum(ui->oberetemperatur->value());
    ui->oberetemperatur->setMinimum(ui->unteretemperatur->value());
    ui->unteretemperatur->setSingleStep(ui->aufloesung->value());
    ui->oberetemperatur->setSingleStep(ui->aufloesung->value());

    //Berechnung des Datenvectors
    werteberechnung(m_PunktListe);

    //Diagramm aktualisieren
    DiagrammWidget dg;
    dg.setUntere_temp(m_untere_temp);
    dg.setObere_temp(m_obere_temp);
    dg.setAufloesung(m_aufloesung);
    dg.setPunkte(m_PunktListe);
    dg.show();
}

float Dialog::temperatur() const{
    return m_T;
}
void Dialog::setTemperatur(float temperatur){
    m_T = temperatur;
}
float Dialog::wiederstand() const{
    return m_RT;
}
void Dialog::setWiederstand(float wiederstand){
    m_RT = wiederstand;
}
float Dialog::bezugswiderstand() const{
    return m_bezugswiderstand;
}
void Dialog::setBezugswiderstand(float bezugswiderstand){
    m_bezugswiderstand = bezugswiderstand;
}
float Dialog::materialkonstante() const{
    return m_materialkonstante;
}
void Dialog::setMaterialkonstante(float materialkonstante){
    m_materialkonstante = materialkonstante;
}
QString Dialog::werkstoff() const{
    return m_werkstoff;
}
void Dialog::setWerkstoff(QString werkstoff){
    m_werkstoff = werkstoff;
}
int Dialog::aufloesung() const{
    return m_aufloesung;
}
void Dialog::setAufloesung(int aufloesung){
m_aufloesung = aufloesung;
}
float Dialog::obere_temp() const{
    return m_obere_temp;
}
void Dialog::setObere_temp(float obere_temp){
    m_obere_temp = obere_temp;
}
float Dialog::untere_temp() const
{
    return m_untere_temp;
}
void Dialog::setUntere_temp(float untere_temp)
{
    m_untere_temp = untere_temp;
}
void Dialog::on_verwerfen_clicked()
{
    ui->werkstoff->setText(m_werkstoff);
    ui->materialkonstante->setValue(m_materialkonstante);
    ui->bezugswiderstand->setValue(m_bezugswiderstand);
    ui->unteretemperatur->setValue(m_untere_temp);
    ui->oberetemperatur->setValue(m_obere_temp);
    ui->aufloesung->setValue(m_aufloesung);

    ui->unteretemperatur->setMaximum(ui->oberetemperatur->value());
    ui->oberetemperatur->setMinimum(ui->unteretemperatur->value());
    ui->unteretemperatur->setSingleStep(ui->aufloesung->value());
    ui->oberetemperatur->setSingleStep(ui->aufloesung->value());
}

void Dialog::on_zuruecksetzen_clicked()
{
    //Standarteinstellungen
    ui->werkstoff->setText("A 34-2/30 (SIEMENS)");
    ui->materialkonstante->setValue(3440);
    ui->bezugswiderstand->setValue(5000);
    ui->unteretemperatur->setValue(0);
    ui->aufloesung->setValue(10);
    ui->oberetemperatur->setValue(300);

    setWerkstoff(ui->werkstoff->text());
    setMaterialkonstante(ui->materialkonstante->value());
    setBezugswiderstand(ui->bezugswiderstand->value());
    setUntere_temp(ui->unteretemperatur->value()+ 272.15);
    setObere_temp(ui->oberetemperatur->value()+ 272.15);
    setAufloesung(ui->aufloesung->value());

    ui->unteretemperatur->setMaximum(ui->oberetemperatur->value());
    ui->oberetemperatur->setMinimum(ui->unteretemperatur->value());
    ui->unteretemperatur->setSingleStep(ui->aufloesung->value());
    ui->oberetemperatur->setSingleStep(ui->aufloesung->value());

    werteberechnung(m_PunktListe);

}

main.cpp

#include "dialog.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog w;
    w.show();

    return a.exec();
}

1 Ответ

0 голосов
/ 30 мая 2018

Как отмечается в комментариях, ваш пример не MCVE .Но, догадываясь, есть пара подсказок:

PunktVektor *m_punkte;         //This is the mentioned vector

и

datenpunkt test = *m_punkte->begin();    <-            //The programm crashs

Если PunktVector не перегружает operator->(), ваш доступ к вектору, вероятно, должен быть

datenpunkt test = m_punkte->begin();    <-            //no dereference (*)


ПЕРЕСМОТР:
В вашем обновленном примере основная проблема заключается в разыменовании итератора end(), который является маркером и не относится к элементу

    datenpunkt test = *m_punkte->begin(); 
    datenpunkt test2 =*m_punkte->end();
    *m_punkte->empty();                

m_punkte->begin() возвращает итератор для первого элемента (если он есть; вектор может быть пустым).*( m_punkte->begin() ) обращается к элементу, к которому относится итератор.
m_punkte->end() возвращает итератор, отмечающий конец контейнера.* (m_punkte->end() ) не определено.
m_punkte->empty() возвращает bool, отражающее, является ли контейнер пустым или нет.*( m_punkte->empty() ) получит доступ к любой области памяти 0 или 1 (обе из которых, вероятно, будут очень плохими.

ПЕРЕСМОТР 2:
При работе с контейнерами важно понимать, как выможет поранить себя. В частности, посмотрите здесь:

void DiagrammWidget::paintEvent(QPaintEvent *event)
{
    QPainter myPainter (this);
    /*if((m_punkte == 0|| m_punkte->size() == 0)){
        myPainter.drawText(100,100,"No Points found!");
        return;
    }*/
    datenpunkt ersterPunkt=*m_punkte->begin();
    datenpunkt startPunkt = ersterPunkt;
    PunktVektor::iterator it;
    for( it = m_punkte->begin()++; it != m_punkte->end(); it++){
        datenpunkt p = *it;

        myPainter.drawLine(startPunkt.temperatur,startPunkt.laenge,                 
            p.temperatur,p.laenge);
        startPunkt = p;
    }
}

Если вы собираетесь сделать это: datenpunkt ersterPunkt=*m_punkte->begin(); , то сначала вы должны проверить, что контейнер пуст.

Container.begin() возвращает итератор к первому элементу контейнера. Если контейнер пуст, этот итератор равен Container.end(). Разыменование этого итератора является хорошим способом аварийного завершения вашей программы.

Попробуйте выполнить рефакторинг вашей программыкак это:

void DiagrammWidget::paintEvent(QPaintEvent *event)
{
    QPainter myPainter (this);
    if( m_punkte == nullptr || m_punkte->empty() ){
    //    myPainter.drawText(100,100,"No Points found!");
        return;
    }
    auto startPunkt = m_punkte->begin();
    for( auto it = ++(m_punkte->begin()); it != m_punkte->end(); ++it){
        auto const& p = *it;

        myPainter.drawLine(startPunkt->temperatur,startPunkt->laenge,                 
            p.temperatur,p.laenge);
        startPunkt = it;
    }
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...