Speicherfehler durch Klassenvariablen - wieso?



  • Hallo zusammen,

    ich fange gerade an, mich als Einsteiger mit Klassen zu befassen.

    Zur Übung möchte ich einen kleinen Vokabeltrainer mit einer GUI (QT) basteln.

    Ich habe nun ein Problem, welches ich nicht wirklich verstehe / lösen kann.

    Wenn das Programm so läuft kommt ein "GLIBC detected" und es stürzt ab.

    Es scheint an den privaten Klassenvariablen zu liegen.
    Wenn ich diese in der "vokabel.cpp" deklariere funktioniert das Programm, aber dann sind es ja globale Klassenvariablen und ich brauche ja Instanzvariablen.

    So sieht der Code aus:

    main.cpp:

    #include "mainwindow.h"
    #include <QApplication>
    
    #include "vokabel.h"
    #include <iostream>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
    
        int anzahlVokabeln=10;
        Vokabel **Vokab = new Vokabel*[anzahlVokabeln];
        for (int i=0; i<anzahlVokabeln; i++)
        {
            Vokab[i]->SetVokabel("hallo","hallo1","hallo2","hallo3"); //Aufruf löst GLIBC aus
        }
    
        return a.exec();
    }
    

    vokabel.h

    #ifndef VOKABEL_H
    #define VOKABEL_H
    
    #include <QObject>
    #include <string>
    
    class Vokabel : public QObject
    {
        Q_OBJECT
    
    public:
        explicit Vokabel(QObject *parent = 0);
    
        void SetVokabel(std::string vokSE, std::string zusSE, std::string vokDE, std::string zusDE);
    
    private:
      std::string vokabelSE;
      std::string zusatzSE;
      std::string vokabelDE;
      std::string zusatzDE;
    
    };
    
    #endif // VOKABEL_H
    

    vokabel.cpp

    #include "vokabel.h"
    #include <string>
    #include <iostream>
    
    Vokabel::Vokabel(QObject *parent) :
        QObject(parent)
    {
    
    }
    
    void Vokabel::SetVokabel(std::string vokSE, std::string zusSE, std::string vokDE, std::string zusDE)
    {
        vokabelDE = vokDE;
        vokabelSE = vokSE;
        zusatzDE  = zusDE;
        zusatzSE =  zusSE;
    }
    

    Wo steckt der Fehler bzw. wie kann ich ihn beseitigen?

    Eine kleine andere Frage hätte ich da ebenfalls noch.
    Diese Schreibweise habe ich so im Netz gefunden: "Vokabel **Vokab = new Vokabel*[anzahlVokabeln];"
    Was bedeutet das doppelte Sternchen?
    Ein einfaches ist ja für einen Pointer und was machen zwei Sterne hintereinander?

    Vielen Dank 🙂



  • Ein Vokabel** ist ein Zeiger auf einen Zeiger auf ein Vokabel .
    Dein Programm stürzt ab weil du über nicht initialisierte Zeiger auf Vokabel zugreifst die nicht existieren.



  • Hmm...

    Irgendwie verstehe ich das nicht.
    Ein Zeiger auf einen Zeiger kann ich mir vorstellen.

    Wieso funktioniert das Programm denn, wenn ich die Variablen in der vokabel.cpp deklariere?

    Könnte ich vielleicht einen Tipp bekommen, wie ich den Fehler beseitigen kann?

    Ich stehe echt auf dem Schlauch 😉

    Danke 🙂



  • Erstmal ein oder mehrere "Vokabel" erzeugen



  • Ich probiere es seit mehreren Stunden, aber ich bekomme es nicht hin.

    Nun habe ich einen anderen Ansatz probiert.
    Ich möchte die Objekte einfach in einen Vektor packen.

    Nun bekomme ich allerdings einen neuen Fehler, der wohl mit meinen Konsturktoren zusammenhängt.
    Allerdings stehe ich hier auch wieder voll auf dem Schlauch.

    Der Fehler ist nun: "Use of deleted function 'Vokabel::Vokabel(const Vokabel&)'"

    Kann mir jemand erklären, warum der Fehler auftritt und wie man ihn beseitigt?

    So sieht der Code nun aus:

    main.cpp

    #include "mainwindow.h"
    #include <QApplication>
    
    #include "vokabel.h"
    #include <iostream>
    #include <vector>
    
    void fillVector(std::vector<Vokabel> &objektvektor)
    {
        for (int i=0; i<10; i++)
        {
            Vokabel vok("Hallo", "hey", "bla", "blub");
            objektvektor.push_back(vok);
        }
    }
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
    
        std::vector<Vokabel> vecOfVoks;
        fillVector(vecOfVoks);
    
        return a.exec();
    }
    

    vokabel.h

    #ifndef VOKABEL_H
    #define VOKABEL_H
    
    #include <QObject>
    #include <string>
    
    class Vokabel : public QObject
    {
        Q_OBJECT
    
    public:
        explicit Vokabel(QObject *parent = 0);
    
        //Überladener Konstruktor
        Vokabel(std::string vokSE, std::string zusSE, std::string vokDE, std::string zusDE);
    
        //Destructor:
        ~Vokabel();
    
        void SetVokabel(std::string vokSE, std::string zusSE, std::string vokDE, std::string zusDE);
    
    private:
      std::string vokabelSE;
      std::string zusatzSE;
      std::string vokabelDE;
      std::string zusatzDE;
    
    };
    
    #endif // VOKABEL_H
    

    vokabel.cpp

    #include "vokabel.h"
    #include <string>
    #include <iostream>
    
    Vokabel::Vokabel(QObject *parent) :
        QObject(parent)
    {}
    
    //Überladener Konstruktor
    Vokabel::Vokabel(std::string vokSE, std::string zusSE, std::string vokDE, std::string zusDE)
    {
        vokabelDE = vokDE;
        vokabelSE = vokSE;
        zusatzDE  = zusDE;
        zusatzSE =  zusSE;
    }
    
    //Destruktor:
    Vokabel::~Vokabel()
    {
    
    }
    
    void Vokabel::SetVokabel(std::string vokSE, std::string zusSE, std::string vokDE, std::string zusDE)
    {
        vokabelDE = vokDE;
        vokabelSE = vokSE;
        zusatzDE  = zusDE;
        zusatzSE  = zusSE;
    }
    

    Vielen Dank 🙂



  • Warum ist Vokabel ein QObject? Das dürfte wohl der Haken sein.

    Wenn du tatsächlich gerade mit Klassen anfängst, solltest du von Qt noch die Finger lassen.



  • Einsteiger123 schrieb:

    Der Fehler ist nun: "Use of deleted function 'Vokabel::Vokabel(const Vokabel&)'"

    Kann mir jemand erklären, warum der Fehler auftritt und wie man ihn beseitigt?

    Warum er auftritt: Es wird ein Copy-Ctor benötigt (für vector), der 'deleted' wurde.
    Beseitigen: Copy-Ctor nicht 'deleten'

    Soweit, so klar.
    Warum der Ctor deleted wurde, liegt daran, dass der Kompiler nicht mehr die Std-Konstruktoren erzeugt, sobald du eigene definierst.
    Abhilfe:

    Vokabel(const Vokabel&) = default;
    


  • Jockelx schrieb:

    Warum der Ctor deleted wurde, liegt daran, dass der Kompiler nicht mehr die Std-Konstruktoren erzeugt, sobald du eigene definierst.

    Eigene "normale" Konstruktoren verhindern nicht dass ein Copy-Ctorerzeugt wird.
    Ich nehme eher an dass hier QObject irgendwie dreinpuscht.

    (@Einsteiger123: Wieso leitest du überhaupt von QObject ab?)



  • Oh ja, hab nur den Konstruktor & die Fehlermeldung gesehen und dann so eine Std-Antwort geschrieben.

    Der Copy-Ctor wird deleted sein, weil QObeject wohl keinen Copy-Ctor hat.



  • Erstmal vielen Dank für die Antworten 🙂

    Vermutlich sollte ich mich erstmal mit reinem C++ befassen, aber die GUI-Elemente von QT sind einfach toll und das "Signal und Slot"-Konzept ist klasse!

    Vokabel wurde von QObject abgeleitet, um später Signale und Slots mit der Vokabelklasse nutzen zu können.

    Kopierkonstruktoren habe ich nachgeschlagen.

    Im Zusammenhang mit QObject habe ich nun folgendes gefunden:

    QObject has neither a copy constructor nor an assignment operator. This is by design. Actually, they are declared, but in a private section with the macro Q_DISABLE_COPY(). In fact, all Qt classes derived from QObject (direct or indirect) use this macro to declare their copy constructor and assignment operator to be private. The reasoning is found in the discussion on Identity vs Value on the Qt Object Model page.

    Das heißt dann wohl, dass ich die Ableitung von QObject entfernen muss und eine zweite Klasse für Signale und Slots brauche, richtig?

    Danke nochmals für die Hilfe 🙂



  • Einsteiger123 schrieb:

    ... das "Signal und Slot"-Konzept ist klasse!

    Nein, das ist grauenvoller Mist (wie du ja auch schon selber feststellen musstest)!

    Einsteiger123 schrieb:

    Vokabel wurde von QObject abgeleitet, um später Signale und Slots mit der Vokabelklasse nutzen zu können.

    Welchen Zweck sollen den Signals/Slots an einer Vokabelklasse haben?



  • manni66 schrieb:

    Einsteiger123 schrieb:

    ... das "Signal und Slot"-Konzept ist klasse!

    Nein, das ist grauenvoller Mist (wie du ja auch schon selber feststellen musstest)!

    Also Momentan finde ich es noch toll und sehe für C++ mit einer GUI keine richtige Alternative zu Qt.
    Ich habe mich zumindest schon ein bisschen in die GUI-Funktionalitäten eingearbeitet und werde bei Qt bleiben.

    manni66 schrieb:

    Einsteiger123 schrieb:

    Vokabel wurde von QObject abgeleitet, um später Signale und Slots mit der Vokabelklasse nutzen zu können.

    Welchen Zweck sollen den Signals/Slots an einer Vokabelklasse haben?

    😃 Ich gebe zu, das war nicht wirklich durchdacht und ich kann hier darauf verzichten. Und für die Zukunft weiß ich nun auch, dass QObject keine Kopierkonstruktoren zulässt 😉


Anmelden zum Antworten