Operatoren überladen von Klassen mit dyn.Variablen: bad_alloc



  • Zudem solltest du dein Schnittstellendesign überdenken.



  • Hallo,

    danke für die Tipps! Ich habe die Idee mit der Vector-Klasse gleich ausprobiert:

    class CTriMatrix
    {
    public:
    	CTriMatrix(void);
    	~CTriMatrix(void);	
    	CTriMatrix(int ndim);
    
    	CTriMatrix operator+(CTriMatrix&);
    
    		vector<complex<double>> dia;
    		vector<complex<double>> sub;
    		vector<complex<double>> super;
    	/*
    		complex<double>* dia;
    		complex<double>* sub;
    		complex<double>* super;
    	*/
    	int ndim;
    };
    

    und entsprechend:

    CTriMatrix::CTriMatrix(int n)
    {
    	ndim=n;
    
    	sub.resize(n,complex<double>(1,0));
    	dia.resize(n,complex<double>(2,0));
    	super.resize(n,complex<double>(3,0));
    		/*
    		sub=new complex<double>[ndim];
    		dia=new complex<double>[ndim];
    		super=new complex<double>[ndim];
    
    		for(int i=0;i<ndim;i++)
    		{
    			sub[i]=complex<double>(1,0);
    			dia[i]=complex<double>(2,0);
    			super[i]=complex<double>(3,0);
    		}
    		*/
    }
    

    Das Speicherproblem hatte sich damit erledigt! Leider ist die Performance drastisch in den Keller gefallen. Das Multiplizieren unter Verwendung der Vectorklasse dauerte mindestens gefühlte 10x länger als mit dem selbstdefiniertem Array. Ich vermute, dass in der Vector-klasse umständlich über Funktionsaufrufe auf die Daten zugegriffen wird. Konnte ich auf den ersten Blick in der vector.h nicht sehen.

    Ich werde also wohl bei den selbstdefinierten Arrays bleiben müssen (?) und mir über die Regel der "großen Drei" Gedanken machen.

    Zudem solltest du dein Schnittstellendesign überdenken.

    Mir ist nicht klar, was genau gemeint ist.

    Grüße,
    Mathias



  • Warum das langsamer sein sollte, bin ich mir nicht sicher - es könnte höchstens sein, daß du zu viele Daten kopierst, die du eigentlich nicht benötigst.

    ostseenashorn schrieb:

    Zudem solltest du dein Schnittstellendesign überdenken.

    Mir ist nicht klar, was genau gemeint ist.

    Grüße,
    Mathias

    Damit ist vor allem gemeint, daß die Implementierungs-Details der Klasse (deine drei Arrays) nichts in der öffentlichen Schnittstelle zu suchen haben - so kann jeder dir mit einem delete[] m.dia; oder ähnlichem die Struktur zerstören, ohne daß deine Klasse etwas davon bemerkt.



  • Warum das langsamer sein sollte, bin ich mir nicht sicher - es könnte höchstens sein, daß du zu viele Daten kopierst, die du eigentlich nicht benötigst.

    Die beiden Varianten unterscheiden sich nur in dem oben kenntlich gemachten Änderungen.

    Damit ist vor allem gemeint, daß die Implementierungs-Details der Klasse (deine drei Arrays) nichts in der öffentlichen Schnittstelle zu suchen haben - so kann jeder dir mit einem delete[] m.dia; oder ähnlichem die Struktur zerstören, ohne daß deine Klasse etwas davon bemerkt.

    Vielleicht sollte ich das erwähnen: ich schreib an einem Algorithmus zur Berechnung eines physikalischen Problems (Lösung Schrödinger-Gleichung). Das Programm ist nicht "öffentlich" (Kunden etc.) und muss SCHNELL sein. Deshalb der Verzicht auf private Variablen.



  • Problem gelöst! Der Fehler war in der Tat, dass infolge der durchgeführten +operation beide Objekte auf denselben Speicherbereich gezeigt haben. Das ursprüngliche Programm ist nur deshalb vorerst nicht abgestürzt, weil die dynamisch erzeugten Arrays im Dekonstruktor nicht explizit wieder freigegeben wurden. Dies hat zwar dazu geführt, dass auf den Speicherbereich korrekt zugegriffen werden konnte (Operation richtig durchgeführt), aber sich der allokierte Speicherbereich zunehmend akkumuliert hat.

    Der Tip mit dem "Regel der große Drei" hat weitergeholfen! Vielen Dank! Habe entsprechend den Copy-Konstruktur hinzugefügt und den Dekonstruktor angepasst (siehe unten)!
    (ob ich den Zuweisungsoperator noch ändern muss?? - da denk ich gleich mal drüber nach 😉 ) Ich gestehe, dass mir das "&"-Zeichen im Argument des Copy-Constructor erst jetzt klar geworden ist. Ohne "&" (Referenz) würde er ja kopieren wollen, während ich noch den Kopiekonstruktor schreibe! Tricky, aber elegant. Habe viel gelernt. C++ ist doch irgendwie logisch.

    Danke für das Feedback zu solch später Stunde. Werde das Forum häufige nutzen! 👍

    CTriMatrix::~CTriMatrix(void)
    {	
    	delete [] sub;
    	delete [] dia;
    	delete [] super;
    }
    
    CTriMatrix::CTriMatrix(const CTriMatrix& mat)
    {
    	ndim=mat.ndim;
            sub=new complex<double>[ndim];
    	dia=new complex<double>[ndim];
    	super=new complex<double>[ndim];
    
            for(int i=0;i<ndim;i++)
    	 {
                  sub[i]=mat.sub[i];
    	      dia[i]=mat.dia[i];
    	      super[i]=mat.super[i];
             }
    }
    


  • Ich kann nicht glauben, dass std::vector langsamer sein soll als rohe C-Arrays (bzw.: Ich bin mir da 100%ig sicher). Welchen Compiler benutzt du, und welche Optimierungen sind eingeschaltet? Für´s Visual Studio gibt´s zumindest einen checked-iterator Zugriff, den man für´s Release Build manuell deaktivieren muss.



  • ostseenashorn schrieb:

    Vielleicht sollte ich das erwähnen: ich schreib an einem Algorithmus zur Berechnung eines physikalischen Problems (Lösung Schrödinger-Gleichung). Das Programm ist nicht "öffentlich" (Kunden etc.) und muss SCHNELL sein. Deshalb der Verzicht auf private Variablen.

    mit öffentdich ist heir nicht gemeint, dass jeder der dein programm bekommt, auch den quellcode sieht, oder das ganze sogar opensource ist, sondern, dass deine member im gesamten quellcode zu sehen sind

    sprich, du könntest irgendwo in deiner main auch "delete[] m.dia" schreiben und deine klasse würde nichts merken und denken "ich bin ok, ich arbeite weiter" und genau dann machts bumm, das universum implodiert und dein computer macht dir beziehungsprobleme



  • ostseenashorn schrieb:

    Das Speicherproblem hatte sich damit erledigt! Leider ist die Performance drastisch in den Keller gefallen. Das Multiplizieren unter Verwendung der Vectorklasse dauerte mindestens gefühlte 10x länger als mit dem selbstdefiniertem Array. Ich vermute, dass in der Vector-klasse umständlich über Funktionsaufrufe auf die Daten zugegriffen wird. Konnte ich auf den ersten Blick in der vector.h nicht sehen.

    Du solltest das mal im Release-Modus testen. Wenn es dann immer noch langsamer ist, dann kann man noch das Interator-Debugging ausschalten.



  • Und dann noch ohne Debugger starten 🙂
    (ja, auch im Release-Modus)



  • Und außerdem heißt es "Destruktor" und nicht "Dekonstruktor".


Anmelden zum Antworten