*** glibc detected *** ./NIS: double free or corruption



  • SeppJ schrieb:

    ...(du hast oft genug hier im Forum gute Tipps bekommen, wie das besser geht)...

    Also mir sagt der Name nichts, wer ist es?


  • Mod

    314159265358979 schrieb:

    SeppJ schrieb:

    ...(du hast oft genug hier im Forum gute Tipps bekommen, wie das besser geht)...

    Also mir sagt der Name nichts, wer ist es?

    Keine Ahnung wer er ist. Apple-Nutzer und kommt von Java, das weiß ich. Mir ist der Name nur schon öfters aufgefallen, weil er immer mal wieder mit ähnlichen Problemen ankommt, die auf "ungewöhnliche" Programmierstrukturen zurückzuführen sind und anscheinend wenig aus den Antworten lernt.

    Da man nicht nach Unregistrierten suchen kann:
    Google: HändyÄndy site:www.c-plusplus.net
    Man lese sich zum Beispiel seinen Thread zu Speicherlöchern durch.





  • Tja, leider beschäftige ich mich nicht den ganzen Tag mit C++ und bin im Gegensatz zu Euch auch kein Experte, daher kann es vorkommen, dass ich gelegentlich dasselbe Frage. Finde ich persönlich jetzt aber auch nicht wirklich schlimm. Über eine Antwort würde ich mich dennoch freuen.



  • Die Antwort ist einfach, und wurde von SeppJ ja schon angedeutet. Deine Verwendung von new ist hier völlig fehl am Platz.

    Abgesehen davon ist bei dir 0 Kapselung zu sehen, aber das dürfte nicht das primäre Problem sein. Der Sinn deines virtuellen Destruktors erschließt sich mir ebenfalls nicht (und ich bezweifle auch, dass du den brauchst, geschweige denn überhaupt verstanden hast.)
    (Das sind übrigens nur 3 Kritikpunkte, da lässt sich noch viel mehr finden, als Beispiel string.h)



  • Danke. Warum soll ich new rausnehmen, wegen "const int"? Ursprünglich war das nur "int", dann sollte man doch afiak ein new verwenden? Der virtual Konstruktor wurde automatisch von der Entwicklungsumgebung erzeugt, da hab ich nicht weiter drauf geachtet.



  • new verwendet man, wenn man dynamischen Speicher braucht und ein RAII Container zu Performance-lastig wäre - also nie. (Selbes gilt übrigens für delete)

    Wenn du eine fixe Anzahl an ints brauchst, dann nimm std::array:

    std::array<int, 42> myints;
    

    Diese anzahl musst du aber schon beim Programmieren (auch Compilezeit genannt) wissen. Wenn erst zur Laufzeit (Zum Beispiel einen User fragen, wie viele Zahlen er eingeben möchte) feststeht, wie viele Zahlen du brauchst, dann nimmt man normalerweise std::vector.

    std::vector<int> myints;
    v.push_back(a);
    v.push_back(b);
    

    Bei beiden kann man mit dem Index-Operator [] auf die Elemente zugreifen.



  • Okay, ich habe alle Arrays durch Vektoren ersetzt:

    #ifndef NIS_1D_H_
    #define NIS_1D_H_
    
    #include <iostream>
    #include <complex>
    #include <cmath>
    #include <vector>
    
    using namespace std;
    
    class NIS_1D {
    public:
    
    	vector<double> Xtrain;
    	int N;
    	vector<double> Xtest;
    	int M;
    	int K;
    	double T;
    	double mu1,mu2,sigma1,sigma2;
    	vector<complex<double> > pExpTR;
    	vector<complex<double> > nExpTR;
    	vector<complex<double> > nExpTE;
    
    	NIS_1D( vector<double>& Xtrain, int N, vector<double>& Xtest, int M, int K, double T, double mu1, double mu2, double sigma1, double sigma2 );
    
    	void preCalculateStuff();
    
    	//Hilfsfunktionen
    	complex<double> complexEuler( double r, double phi );
    };
    
    #endif /* NIS_1D_H_ */
    
    #include "NIS_1D.h"
    
    NIS_1D::NIS_1D( vector<double>& Xtrain_, int N_, vector<double>& Xtest_, int M_, int K_, double T_,
    		        double mu1_, double mu2_, double sigma1_, double sigma2_ ) : Xtrain(Xtrain_), Xtest(Xtest_) {
    	N = N_;
    	M = M_;
    	K = K_;
    	T = T_;
    	mu1 = mu1_;
    	mu2 = mu2_;
    	sigma1 = sigma1_;
    	sigma2 = sigma2_;
    
    	preCalculateStuff();
    }
    
    void NIS_1D::preCalculateStuff() {
    
    	int KLength = 2*K+1;
    
    	pExpTR.resize( sizeof(double), KLength*N );
    	nExpTR.resize( sizeof(double), KLength*N );
    	nExpTE.resize( sizeof(double), KLength*M );
    
    	//Bei 1D wird kein Hyperbolisches Kreuz benötigt. Was soll das auch schon sein?
    	for( int k = -K; k <= K; ++k ) {
    		for( int i = 0; i < N; ++i ) {
    			int index = k+i*KLength;
    			pExpTR[index] = complexEuler( 1,  2*M_PI*k/T*Xtrain[i] );
    			nExpTR[index] = complexEuler( 1, -2*M_PI*k/T*Xtrain[i] );
    		}
    
    		for( int i = 0; i < M; ++i ) {
    			int index = k+i*KLength;
    			nExpTE[index] = complexEuler( 1, -2*M_PI*k/T*Xtest[i] );
    		}
    	}
    
    }
    
    //Hilfsfuntkionen
    complex<double> NIS_1D::complexEuler( double r, double phi ) {
    	return complex<double>( r*cos( phi ),r*sin( phi ) );
    }
    

    und NIS.cpp

    #include "NIS_1D.h"
    
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    int main(int argc, char** argv)
    {
    	vector<double> Xtrain;
    	Xtrain.push_back( 1.0 );
    	Xtrain.push_back( 2.0 );
    	Xtrain.push_back( 3.0 );
    	int N = Xtrain.size();
    
    	vector<double> Xtest;
    	Xtest.push_back( 5.5 );
    	Xtest.push_back( 6.5 );
    	Xtest.push_back( 7.5 );
    	int M = Xtest.size();
    
    	int K = 10;
    	double T = 2.1;
    	double mu1 = 2.9;
    	double mu2 = 2.1;
    	double sigma1 = 7.4;
    	double sigma2 = 8.3;
    
    	NIS_1D nis( Xtrain, N, Xtest, M, K, T, mu1, mu2, sigma1, sigma2 );
    	cout << "done" << endl;
    }
    

    Ich erhalte nach wie vor denselben Fehler:

    NIS_Fkt> ./NIS
    done
    *** glibc detected *** ./NIS: double free or corruption (out): 0x000000000060ee40 ***
    ======= Backtrace: =========
    /lib64/libc.so.6(+0x73226)[0x2aeb02ebe226]
    /lib64/libc.so.6(cfree+0x6c)[0x2aeb02ec2fcc]
    ./NIS[0x401d4c]
    ./NIS[0x401b72]
    ./NIS[0x4017d5]
    ./NIS[0x401330]
    ./NIS[0x40112f]
    ./NIS[0x401037]
    /lib64/libc.so.6(__libc_start_main+0xfd)[0x2aeb02e69b7d]
    ./NIS[0x400d89]
    ======= Memory map: ========
    usw. ...

    Woran kann es jetzt noch liegen?


  • Mod

    Wenn du's so machst wie Pi (und andere) hier vorschlagen, sollten schon einmal eine Menge Probleme verschwinden. Dann werden deine Objekte nämlich auf einmal auf "magische" Weise vernünftig kopier- und zuweisungsfähig. Das Problem derzeit ist vermutlich da drauf zurück zu führen, dass du die Regel der großen Drei massivst verletzt.

    Was aber auch noch ein großes Problem sein könnte ist das memcpy. Das ist auch eine Todsünde auf Klassen mit komplexen Konstruktoren. Wenn du es wie oben machst, sollte diese Komplexität zwar wegfallen und es "sollte" funktionieren, aber es gibt keinen Grund etwas zu riskieren. Wer weiß schon, wie complex intern genau aufgebaut ist? Ein normales copy macht genau das gleiche und ist dabei aber sicher.

    Das sind erst einmal die schlimmsten Fehler, vermutlich wird's auch funktionieren, wenn du das umsetzt. Und wenn du noch ein bisschen an deinem Stil arbeitest und Variablen möglichst lokal und mit sprechenden Namen deklarierst, kann man sich den Code sogar durchlesen und verstehen, falls du doch noch Fehler haben solltest.



  • Erstell ein neues Projekt oder wenn du weisst wie man das Projekt leert, dann leere es.


  • Mod

    HändyÄndy schrieb:

    NIS_Fkt> ./NIS
    done
    *** glibc detected *** ./NIS: double free or corruption (out): 0x000000000060ee40 ***
    ======= Backtrace: =========
    /lib64/libc.so.6(+0x73226)[0x2aeb02ebe226]
    /lib64/libc.so.6(cfree+0x6c)[0x2aeb02ec2fcc]
    ./NIS[0x401d4c]
    ./NIS[0x401b72]
    ./NIS[0x4017d5]
    ./NIS[0x401330]
    ./NIS[0x40112f]
    ./NIS[0x401037]
    /lib64/libc.so.6(__libc_start_main+0xfd)[0x2aeb02e69b7d]
    ./NIS[0x400d89]
    ======= Memory map: ========
    usw. ...
    

    Woran kann es jetzt noch liegen?

    Ein Stacktrace aus einem Programm ohne Debuginformationen ist reichlich nutzlos. Compilier mal mit Debuginforamtionen, dann sieht man wenigstens, wo der Fehler ist. Und wenn du das schon hast, dann schmeiß auch mal den Debugger an und versuch herauszufinden, was da los ist. Der Debugger ist das wohl wichtigste Werkzeug eines Programmierers (wichtiger als Editor und Compiler würde ich sagen), du solltest unbedingt damit umgehen können. Im Internet kannst du Tutorials zum Debugger in deiner Toolchain finden.



  • Ich habe den Fehler gefunden, er entstand dadurch, dass bei der for-Schleife

    for( int k = -K; k <= K; ++k )

    der Index k negativ sein konnte, dadurch habe ich im Vektor auf ein negativ indiziertes Element, das es ja nicht gibt, zugegriffen und es kam zu einem Fehler.
    Außerdem war das hier auch noch falsch:

    pExpTR.resize( sizeof(double), KLengthN );
    nExpTR.resize( sizeof(double), KLength
    N );
    nExpTE.resize( sizeof(double), KLength*M );

    Ich habe es ersetzt durch

    complex<double> zero(0,0);
    pExpTR.resize( KLengthN, zero );
    nExpTR.resize( KLength
    N, zero );
    nExpTE.resize( KLength*M, zero );

    Ich habe die for-Schleife entsprechend repariert:

    for( int k = 0; k < KLength; ++k )

    Vielen Dank für die Unterstützung und Hinweise!


Anmelden zum Antworten