double free or corruption (top)



  • Hallo,

    meine erster Eintrag hier.
    Ich habe mir die folgende Klasse Matrix geschrieben, die auch soweit funktioniert.

    template<typename T>
    class matrix{
    public:
        matrix(T zeilen_, T spalten_):zeilen(zeilen_),spalten(spalten_){matrix_=new T[zeilen*spalten];}
        ~matrix(){delete[] matrix_;}
    
        T size_zeilen(){return(zeilen);}
        T size_spalten(){return(spalten);}
        T& operator()(T i, T j){return(matrix_[((i*spalten)+j)]);}
        T* operator[](T i){return(matrix_+i*spalten);}
    
    private:
        T zeilen, spalten;
        T *matrix_;
    };
    

    Mit dem Additionsoperator

    template<typename T>
    matrix<T> operator+( matrix<T> lhs, matrix<T> rhs){
    
        matrix<T> neu(lhs.size_zeilen(),lhs.size_spalten());
        for(int i=0;i<lhs.size_zeilen();i++)
        {
            for(int j=0;j<lhs.size_spalten();j++)
            {
                neu(i,j) = lhs(i,j)+rhs(i,j);
            }
        }
    
        //cout<<&neu(10,10)<<endl;
        return(neu);
    }
    

    Main Funktion

    int main()
    {
        matrix<int> B(20,20);
        matrix<int> A(20,20);
    
        for(int i =0;i<20;i++){
            for(int j =0;j<20;j++){
                B(i,j)=1;
                A(i,j) = 2;
                //cout<<B[i][j];
            }
        }
    
        matrix<int> Z(20,20);
        Z = A + B;
        for(int i = 0;i<19;i++)
        {
            for(int j = 0;j<20;j++)
            {
                cout<<Z(i,j);
            }
            cout<<endl;
        }
    
        //cout<<&Z(10,10)<<endl;
    
        return 0;
    }
    

    Folgendes Problem stellt sich ein.
    Deklariere und Initialisiere die Matrizen A und B diese sollen zu Z addiert werden, funktioniert.
    Nun beim übergeben der Matrix neu (Summe von A und B), die am ende gelöscht wird, jedoch Z zeigt immer noch auf neu und beim return 0 kommt halt logischerweise folgende Fehlermeldung: double free or corruption (top).
    Z zeigt auf einen Speicherbereich der nicht mehr existiert....

    Wie löse ich dieses Problem?

    Vielen Dank 🙂



  • Nein, Z ist ja kein Pointer. Z ist ein Objekt auf dem Stack.
    Das Problem ist, dass du mit neu ein Objekt zurückgibst, welches selbst einen Pointer namens matrix_ hat.

    Zum Verständis: wenn das Objekt zurückgegeben wird, werden die Elemente 1:1 vom alten ( neu ) zum neuen ( Z ) Objekt zugewiesen. Auch der matrix_ -Pointer. Aber danach wird für neu der Destruktor aufgerufen, und der Speicherbereich, auf den der Pointer zeigte, wird ungültig.

    Wenn am Ende von main Z zerstört werden soll, wird WIEDER die gleiche Adresse zum Freigeben weitergegeben. Der Speicherbereich wurde aber bereits freigegeben.

    Lösung: noch den =-Operator überladen, damit dieser eine tiefe Kopie deines Objektes macht. Damit jedes Objekt seinen eigenen Speicherbereich hat.



  • Benutze std::vector statt new/delete

    operator+ sollte sicher auch keine Kopien machen.

    return ist kein Funktionsaufruf, () ist überflüssig



  • Danke für die Antworten.

    Hab den Operator= folgend überladen damit geht es nun.

    matrix<T>& operator=(matrix<T> rhs){
            if (this == &rhs)
                return *this;
    
            swap(matrix_,rhs.matrix_);
            return *this;
        }
    


  • Fehlt immer noch Copyctor.
    Mach dir dein Leben nicht schwerer als ohnehin und benutze std::vector. Dann sparste dir das schreiben von Konstruktor, Destruktor, Kopierkonstruktor und Assignmentoperator bei keinen Geschwindigkeitsverlust.



  • User01815 schrieb:

    Danke für die Antworten.

    Hab den Operator= folgend überladen damit geht es nun.

    matrix<T>& operator=(matrix<T> rhs){
            if (this == &rhs)
                return *this;
    
            swap(matrix_,rhs.matrix_);
            return *this;
        }
    

    Das if kannste dir sparen, das wird nie wahr sein.


Anmelden zum Antworten