kaputter Heap: double free or corruption (out) beim löschen des Objektes



  • Hallo an alle,
    ich bekomme immer einen Pointerfehler, wenn ich ein Objekt löschen möchte, nur finde ich den nicht.
    Kann mir bitte jemand mit ein paar zusätzlichen Augen, und mehr Erfahrung/Wissen helfen?

    Ich erstelle in einer Funktion ein Objekt auf dem Heap.

    ViewQuerryOption *newView= new ViewQuerryOption();
    newView->tableViewOption(&querry, &viewName, &TqmStorage);
    

    Das möchte ich am Ende der Funktion nun wie folgt löschen.

    delete newView;
    

    Nur leider bekomme ich an der Stelle, genauer beim Destruktor des Objekts, einen Pointer Fehler [...] "double free or corruption (out)" [...]
    Durch googeln nach diesem Fehler finde ich zahlreiche Beispiele wie ich mir noch so den Speicher zerschießen kann, nur nichts was ich adaptieren kann, zumindest seh ich es nicht.

    Hier der Code zu "ViewQuerryOption.h"

    #ifndef VIEWQUERRYOPTION_H
    #define VIEWQUERRYOPTION_H
    
    #include "MainTable.h"
    #include "ModulQuery.h"
    
    #include <QWidget>
    #include <QtGui>
    #include <QMap>
    
    using namespace std;
    
    class ViewQuerryOption : public QDialog
    {
        Q_OBJECT
    public:
        explicit ViewQuerryOption(QWidget *parent = 0);
        ~ViewQuerryOption();
        void tableViewOption(QString *querry, QString *viewName, QMap <QString, ModulQuery> *TqmStorage);
    private:
        MainTable *ptrAufTable;
    
        QCheckBox plz;
        QCheckBox number;
        QCheckBox city;
        QCheckBox street;
    
        QCheckBox firstName;
        QCheckBox lastName;
        QCheckBox male;
    
        QCheckBox roll;
        QCheckBox companyName;
    
        QCheckBox phone;
        QCheckBox mail;
    
        QRadioButton  rbUser;
        QRadioButton  rbFirma;
        QRadioButton  rbInstanz;
    
        QComboBox  whereSelect;
        QComboBox  relation;
        QLineEdit  searcher;
        QLineEdit  nameOfV;
    
        QVBoxLayout  vBoxLall;
        QVBoxLayout  vRadioL;
        QVBoxLayout  vBoxLaddress;
        QVBoxLayout  vBoxLinstanz;
        QVBoxLayout  vBoxLnext;
        QVBoxLayout  vBoxLcontact;
        QVBoxLayout  vL;
        QVBoxLayout  vButtonNemaL;
    
        QHBoxLayout  hWhereL;
        QHBoxLayout  hInAnL;
        QHBoxLayout  hNeCoL;
        QHBoxLayout  hL;
        QHBoxLayout  hViewLabelL;
        QHBoxLayout  hFunctionButtonL;
    
        QPushButton  ok;
        QPushButton  cancel;
    
        QGroupBox  preSelect;
        QGroupBox  selectViews;
        QGroupBox  selectWhere;
        QGroupBox  nameLabel;
    
        QLabel  addressData;
        QLabel  instanzData;
        QLabel  nextData;
        QLabel  contectData;
        QLabel  nameOfView;
    
        QSignalMapper  signalMapper;
        QString  *makingQuery;
        QString  *localViewName;
        QMap <QString, ModulQuery> *localTmpMap;
    
        QMessageBox msgBox;
    signals:
    
    public slots:
        void okPushed();
        void createQuery();
        void addToComboBox(const int &CheckBoxName);
    
    };
    
    #endif // VIEWQUERRYOPTION_H
    

    Hier der Code des Objektes "ViewQuerryOption.cpp"

    #include "ViewQuerryOption.h"
    
    ViewQuerryOption::ViewQuerryOption(QWidget *parent) : QDialog(parent)
    {
        //Erzeugung aller grafischen bestandteile des fensteres und verschachtelung in Layouts
    
        //Hinzufügen der Objete, deren Signale gebündelt werden
        signalMapper.setMapping(&plz,1);
        signalMapper.setMapping(&number,2);
        signalMapper.setMapping(&city,3);
        signalMapper.setMapping(&street,4);
        signalMapper.setMapping(&firstName,5);
        signalMapper.setMapping(&lastName,6);
        signalMapper.setMapping(&male,7);
        signalMapper.setMapping(&roll,8);
        signalMapper.setMapping(&companyName,9);
        signalMapper.setMapping(&phone,10);
        signalMapper.setMapping(&mail,11);
    
        // Beschriftung der RadioButton
        rbInstanz.setText("Instanz / Person");
        rbFirma.setText("Firma");
        rbUser.setText("D-Manager Nutzer");
    
        // vertikales Layout für die Radiobutton in der oberen GroupBox
        vRadioL.addWidget(&rbInstanz);
        vRadioL.addWidget(&rbFirma);
        vRadioL.addWidget(&rbUser);
        //Fügt der GroupBox das Layout mit den 3 RadioButton hinzu
        preSelect.setLayout(&vRadioL);
    
        // Beschriftung der Labels
        addressData.setText("Adressdaten");
        instanzData.setText("Instanz / Personendaten");
        nextData.setText("weitere Informationen");
        contectData.setText("Kontaktdaten");
        nameOfView.setText("Name der View:");
    
        // Beschriftung der CheckBoxen
        street.setText("Strasse");
        number.setText("Hausnummer");
        plz.setText("Postleitzahl");
        city.setText("Stadt");
        male.setText("Anrede");
        lastName.setText("Nachname");
        firstName.setText("Vorname");
        companyName.setText("Firmenname");
        roll.setText("Instanzname");
        phone.setText("Telefon");
        mail.setText("E-Mail");
    
        // vertikales Layout für die Checkboxen zur Adresse
        vBoxLaddress.addWidget(&addressData);
        vBoxLaddress.addWidget(&street);
        vBoxLaddress.addWidget(&number);
        vBoxLaddress.addWidget(&plz);
        vBoxLaddress.addWidget(&city);
    
        // vertikales Layout für die Checkboxen zur Instanz
        vBoxLinstanz.addWidget(&instanzData);
        vBoxLinstanz.addWidget(&male);
        vBoxLinstanz.addWidget(&lastName);
        vBoxLinstanz.addWidget(&firstName);
    
        // Horizontales Layout für die vertikalen Layouts der Checkboxen zur Adresse und Instanz
        hInAnL.addLayout(&vBoxLinstanz);
        hInAnL.addLayout(&vBoxLaddress);
    
        // vertikales Layout für die Checkboxen zur weiteren Daten
        vBoxLnext.addWidget(&nextData);
        vBoxLnext.addWidget(&companyName);
        vBoxLnext.addWidget(&roll);
    
        // vertikales Layout für die Checkboxen zur Kontaktdaten
        vBoxLcontact.addWidget(&contectData);
        vBoxLcontact.addWidget(&phone);
        vBoxLcontact.addWidget(&mail);
    
        // vertikales Layout für die Radiobutton in der mittleren GroupBox
        hNeCoL.addLayout(&vBoxLnext);
        hNeCoL.addLayout(&vBoxLcontact);
    
        // Fügt die 2 horizontalen layouts nochmal i ein vertikales zusammen
        vBoxLall.addLayout(&hNeCoL);
        vBoxLall.addLayout(&hInAnL);
    
        //Fügt der mittleren GroupBox das Layout mit den CheckBoxen hinzu
        selectViews.setLayout(&vBoxLall);
    
        //Fügt den Comboboxen die Standard Auswahlmöglichkeiten hinzu
        whereSelect.addItem("Suche verfeinern");
        relation.addItem("=");
        relation.addItem("<");
        relation.addItem(">");
    
        // vertikales Layout für die untere Filtefunktion
        hWhereL.addWidget(&whereSelect);
        hWhereL.addWidget(&relation);
        hWhereL.addWidget(&searcher);
    
        // fügt layout GroupBox hinzu
        selectWhere.setLayout(&hWhereL);
    
        // Button vorbereiten
        ok.setText("OK");
        cancel.setText("Abbrechen");
        //Namenslabel und Funktionsbutten zu einem Layout formen
        hViewLabelL.addWidget(&nameOfView);
        hViewLabelL.addWidget(&nameOfV);
        hFunctionButtonL.addWidget(&ok);
        hFunctionButtonL.addWidget(&cancel);
        vButtonNemaL.addLayout(&hViewLabelL);
        vButtonNemaL.addLayout(&hFunctionButtonL);
    
        nameLabel.setLayout(&vButtonNemaL);
    
        // Fügt die 3 Groupboxen eine horizontalen Layout hinzu
        hL.addWidget(&preSelect);
        hL.addWidget(&selectViews);
        vL.addLayout(&hL);
        vL.addWidget(&selectWhere);
        vL.addWidget(&nameLabel);
    
        // Setzt das gesammte Layout
        setLayout(&vL);
    
        QObject::connect(&ok,SIGNAL(clicked()),this,SLOT(okPushed()));
        QObject::connect(&cancel,SIGNAL(clicked()),this,SLOT(close()));
    
        //Immer wenn eine Checkbox angeklickt wurde und sich damit ihr Status geänder hatte wird diese CheckBox
        //in den Mappere geschrieben
        QObject::connect( &plz, SIGNAL(clicked()), &signalMapper, SLOT(map()) );
        QObject::connect( &number, SIGNAL(clicked()), &signalMapper, SLOT(map()) );
        QObject::connect( &city, SIGNAL(clicked()), &signalMapper, SLOT(map()) );
        QObject::connect( &street, SIGNAL(clicked()), &signalMapper, SLOT(map()) );
        QObject::connect( &firstName, SIGNAL(clicked()), &signalMapper, SLOT(map()) );
        QObject::connect( &lastName, SIGNAL(clicked()), &signalMapper, SLOT(map()) );
        QObject::connect( &male, SIGNAL(clicked()), &signalMapper, SLOT(map()) );
        QObject::connect( &roll, SIGNAL(clicked()), &signalMapper, SLOT(map()) );
        QObject::connect( &companyName, SIGNAL(clicked()), &signalMapper, SLOT(map()) );
        QObject::connect( &phone, SIGNAL(clicked()), &signalMapper, SLOT(map()) );
        QObject::connect( &mail, SIGNAL(clicked()), &signalMapper, SLOT(map()) );
    
        QObject::connect(&signalMapper, SIGNAL(mapped(const int&)), this, SLOT(addToComboBox(const int &)) );
    }
    
    ViewQuerryOption::~ViewQuerryOption()
    {
    
    }
    
    //fügt die angehakten spalten zur ComboBox hinzu um diese weiter zu nutzen.
    void ViewQuerryOption::addToComboBox(const int &CheckBoxName)
    {
    
        switch (CheckBoxName)
        {
        case 1 :
            if (plz.isChecked())
            {
                whereSelect.addItem("PLZ");
            }else
            {
                whereSelect.removeItem(whereSelect.findText("PLZ"));
            }
        break;
        case 2 :
            if (number.isChecked())
            {
                whereSelect.addItem("Hausnummer");
            }else
            {
                whereSelect.removeItem(whereSelect.findText("Hausnummer"));
            }
        break;
        case 3 :
            if (city.isChecked())
            {
                whereSelect.addItem("Stadt");
            }else
            {
                whereSelect.removeItem(whereSelect.findText("Stadt"));
            }
        break;
        case 4 :
            if (street.isChecked())
            {
                whereSelect.addItem("Strasse");
            }else
            {
                whereSelect.removeItem(whereSelect.findText("Strasse"));
            }
        break;
        case 5 :
            if (firstName.isChecked())
            {
                whereSelect.addItem("Vorname");
            }else
            {
                whereSelect.removeItem(whereSelect.findText("Vorname"));
            }
        break;
        case 6 :
            if (lastName.isChecked())
            {
                whereSelect.addItem("Nachname");
            }else
            {
                whereSelect.removeItem(whereSelect.findText("Nachname"));
            }
        break;
        case 7 :
            if (male.isChecked())
            {
                whereSelect.addItem("Anrede");
            }else
            {
                whereSelect.removeItem(whereSelect.findText("Anrede"));
            }
        break;
        case 8 :
            if (roll.isChecked())
            {
                whereSelect.addItem("Rolle");
            }else
            {
                whereSelect.removeItem(whereSelect.findText("Rolle"));
            }
        break;
        case 9 :
            if (companyName.isChecked())
            {
                whereSelect.addItem("Firma");
            }else
            {
                whereSelect.removeItem(whereSelect.findText("Firma"));
            }
        break;
        case 10 :
            if (phone.isChecked())
            {
                whereSelect.addItem("Telefon");
            }else
            {
                whereSelect.removeItem(whereSelect.findText("Telefon"));
            }
        break;
        case 11 :
            if (mail.isChecked())
            {
                whereSelect.addItem("E-Mail");
            }else
            {
                whereSelect.removeItem(whereSelect.findText("E-Mail"));
            }
        break;
    
        }
    }
    
    void ViewQuerryOption::okPushed()
    {
        if (nameOfV.text()=="")
        {
            const wchar_t* QboxText = L"Bitte geben Sie einen Namen für die neue Ansicht ein!\n";
            msgBox.setWindowTitle("Name fehlt");
            msgBox.setIcon(QMessageBox::Warning);
            msgBox.setText(QString(QString::fromWCharArray(QboxText)));
            msgBox.exec();
        }else if(localTmpMap->contains(nameOfV.text()))
        {
            /*ModulQuery foo;
            foo = localTmpMap->value(nameOfV.text());
            cout <<"Querry: " <<foo.getQuery().toStdString() <<endl;
            */
            const wchar_t* QboxText = L"Dieser Name existiert bereits! Bitte wählen Sie einen anderen.\n";
            msgBox.setWindowTitle("Name existiert");
            msgBox.setIcon(QMessageBox::Warning);
            msgBox.setText(QString(QString::fromWCharArray(QboxText)));
            msgBox.exec();
        }else
        {
            this->createQuery();
            this->close();
        }
    
    }
    /*
     * Übernimmt die Zeiger auf den Querry und den Tabnamen auf Klasseenvariablen
     * und startet die View.
    */
    void ViewQuerryOption::tableViewOption(QString *query, QString *viewName, QMap <QString, ModulQuery> *TqmStorage)
    {
        makingQuery=query;
        localViewName=viewName;
        localTmpMap = TqmStorage;
        this->exec();
    }
    
    /*
     * Erstellt aus den ANgaben des Nutuzers einen gültigen SQL Query
    */
    void ViewQuerryOption::createQuery()
    {
    
        *makingQuery="SELECT";
    
        if (plz.isChecked())
        {*makingQuery=*makingQuery+" plz,";}
    
        if (number.isChecked())
        {*makingQuery=*makingQuery+" hausnummer,";}
    
        if (city.isChecked())
        {*makingQuery=*makingQuery+" ort,";}
    
        if (street.isChecked())
        {*makingQuery=*makingQuery+" strasse,";}
    
        if (firstName.isChecked())
        {*makingQuery=*makingQuery+" vorname,";}
    
        if (lastName.isChecked())
        {*makingQuery=*makingQuery+" nachname,";}
    
        if (male.isChecked())
        {*makingQuery=*makingQuery+" anrede,";}
    
        if (roll.isChecked())
        {*makingQuery=*makingQuery+" rollenname,";}
    
        if (companyName.isChecked())
        {*makingQuery=*makingQuery+" firmenname,";}
    
        if (phone.isChecked())
        {*makingQuery=*makingQuery+" telefonnummer, beschreibung,";}
    
        if (mail.isChecked())
        {*makingQuery=*makingQuery+" mail,";}
    
        //löscht das letzte Komma bevor FROM geschrieben wird. SQL Fehler vermeiden!
         makingQuery->remove((makingQuery->length()-1),1);
        *makingQuery=*makingQuery+" FROM";
    
        if (plz.isChecked() || number.isChecked() || city.isChecked() || street.isChecked())
        {*makingQuery=*makingQuery+" dm_anschrift,";}
    
        if (firstName.isChecked() || lastName.isChecked() || male.isChecked())
        {*makingQuery=*makingQuery+" dm_person,";}
    
        if (phone.isChecked())
        {*makingQuery=*makingQuery+" dm_phone,";}
    
        if (mail.isChecked())
        {*makingQuery=*makingQuery+" dm_mail,";}
    
        //löscht das letzte Komma vor WHERE geschrieben wird. SQL Fehler vermeiden!
        makingQuery->remove((makingQuery->length()-1),1);
    
        if (whereSelect.currentText()=="Suche verfeinern")
        {
        }else
        {
            *makingQuery=*makingQuery+" WHERE ";
            *makingQuery=*makingQuery+whereSelect.currentText();
            *makingQuery=*makingQuery+relation.currentText();
            *makingQuery=*makingQuery+"'";
            *makingQuery=*makingQuery+searcher.text();
            *makingQuery=*makingQuery+"'";
    
        }
        *localViewName=nameOfV.text();
    }
    

    BTW.: Ich arbeite hier mit der QT Bibliothek da es sich aber um Speicherfehler handelt dachte ich ein C++ Forum ist geeigneter. Ich weis es ist viel Code, das Meiste sind Form Objekte die in Layouts geschachtelt werden.

    Ist die Funktion ein gängiger Workaround oder liegt da schon der Fehler begraben?

    void ViewQuerryOption::tableViewOption(QString *query, QString *viewName, QMap <QString, ModulQuery> *TqmStorage)
    {
        makingQuery=query;
        localViewName=viewName;
        localTmpMap = TqmStorage;
        this->exec();
    }
    

    Vielen Dank schonmal für eure Hilfe!

    Gruß Meho



  • Tja, hunderte Codezeilen, aber new und delete einfach nur aus dem Zusammenhang gerissen. Das ist ziemlich sinnlos.

    Geraten: Qt löscht deine View schon, dein delete ist dann eins zu viel



  • Jepp, Qt löscht nach close():
    http://qt-project.org/doc/qt-5/qwidget.html#close



  • 😮
    Also auf der einen Seite bin ich über eure schnelle und kompetente Hilfe sehr beeindruckt und sehr dankbar!
    Auf der anderen Seite sucht, googelt und wühlt man an einem Fehler, stunden lang, den andere in nicht mal 5 min beantwortet haben! 😡

    Ich führe

    this->close();
    

    in "void ViewQuerryOption::okPushed()" aus und erbe von QDialog also passt
    "If the widget has the Qt::WA_DeleteOnClose flag, the widget is also deleted."

    Vielen Dank für eure schnelle Hilfe!

    BTW: Kann ich irgenwie nachvolziehen ob das Objekt gelöscht wurde im Debugger habe ich nichts gefunden, da sieht man nur den Stack.

    Gruß Meho



  • Meho schrieb:

    BTW: Kann ich irgenwie nachvolziehen ob das Objekt gelöscht wurde im Debugger habe ich nichts gefunden, da sieht man nur den Stack.

    Haltepunkt oder Ausgabe im Destruktor



  • Meho schrieb:

    Auf der anderen Seite sucht, googelt und wühlt man an einem Fehler, stunden lang, den andere in nicht mal 5 min beantwortet haben! 😡

    Oft ist es leider andersrum, viele fragen einfach in Foren nach, ohne auch nur 2 min selbst nachzulesen oder google zu fragen...



  • Meho schrieb:

    Also auf der einen Seite bin ich über eure schnelle und kompetente Hilfe sehr beeindruckt und sehr dankbar!
    Auf der anderen Seite sucht, googelt und wühlt man an einem Fehler, stunden lang, den andere in nicht mal 5 min beantwortet haben! 😡

    Das nennt man Erfahrung 😉

    Erfahrung gewinnt man (auch), indem man Fehler macht!


Anmelden zum Antworten