Speicherleaks



  • erstmal danke für die vielen Antworten 🙂

    gedächtnislücke schrieb:

    Ich wiederhohle: Warum

    leg* m_bein[6];
    

    und nicht

    leg m_bein[6];
    

    ?

    Wie soll ich leg m_bein inizialisieren? Wie rufe ich dann im Konstruktor von Hexapod den Konstruktor von leg auf?

    Xebov schrieb:

    Warum hälst du soviele Daten als Zeiger und nicht als normale Variable zB:

    leg*                m_bein[6];
    D3DXVECTOR3*        m_CamPos;
    

    naja weil dies Daten sind die diesem Objekt nicht gehören, sie aber darauf zugreifen müssen. m_CamPos ist ein D3DXVECTOR3 eines anderen Objekts, der aber von Leg benötigt wird. und damit leg immer den aktuellen vektor hat bekommt leg eben einen Pointer zum Originalvektor. Alternativ müsste Leg einen Pointer zum Objekt View_Light bekommen um mit get sich den vektor immer zu holen. die Variante find ich aber doof weil ich zu viele Kreisschlüsse bekomme was Pointertausch meiner Objekte angeht...

    manni66 schrieb:

    Was ist mit campos?

    Wie gesagt CamPos ist ein Pointer auf die Richtige CamPos. Wird auch im Konstruktor übergeben.



  • Ich sehe keinen operator=() oder Kopier-K'tor.
    Erfahrungsgemäß brauchst Du die aber, wenn Du mit Pointern hantierst...("Rule of three")



  • Furble Wurble schrieb:

    Erfahrungsgemäß brauchst Du die aber, wenn Du mit Pointern hantierst...("Rule of three")

    jein. Das gilt nur dann, wenn man Pointer selbst erzeugt. Teilweise scheinen hier Pointer auf extern erstellte Objekte gehalten zu werden. Bei diesen Pointern reicht es, die Adresse zu kopieren.

    Da aber m_bein im Objekt erzeugt wird, sind die erwähnten Methoden notwendig.



  • daddy_felix schrieb:

    Furble Wurble schrieb:

    Erfahrungsgemäß brauchst Du die aber, wenn Du mit Pointern hantierst...("Rule of three")

    jein. Das gilt nur dann, wenn man Pointer selbst erzeugt.

    Nicht einmal unbedingt dann. Wenn man intelligente Smart-Pointer mit Kopiersemantik hat, kann man sich auch die Big Three sparen...



  • ok ich ich glaube ich hab verstanden was ihr damit meint, bzw wo das Problem liegt.
    Aber ich weiß noch nicht so recht ob ich das jetzt richtig gemacht habe. für Hexapod hab ich jetzt keinen CopyK. und keinen Operator hinzugefügt da Hexapod einzigartig bleibt. Für aber Leg schon.
    Ich stell mich grade nur etwas an, und weiß nicht wie ich den Copyoperator jetzt richtig nutze, um m_bein in Hexapod richtig zu erstellen.
    Ich habs jetzt ohne pointer versucht, aber jetzt bekomm ich folgende meldung im Konstruktor von Hexapod:

    für die Klasse "leg" ist kein standard Konstruktor vorhanden
    

    Hexapod .h und .cpp

    #ifndef HEXAPOD_H_CL90
    #define HEXAPOD_H_CL90
    
    #include "init_configuration.h"
    #include "leg.h"
    
    class Hexapod
    {
    	public:
    		Hexapod(D3DXVECTOR3* CamPos);
    		~Hexapod();
    
    		leg*				get_leg(int number);
    
    	private:
    
    		leg				m_bein[6];
    
    		D3DXVECTOR3*		m_CamPos;
    };
    
    #endif
    
    #include "hexapod.h"
    
    Hexapod :: Hexapod(D3DXVECTOR3* CamPos)
    {
    	m_CamPos	= CamPos;
    
    	unsigned int i;
    	for(i = 0; i < 6; i++)
    	{
    		//m_bein[i] = new leg(m_CamPos, 0.0f, 0.0f, 0.0f, 0.0f);
    		m_bein[i] = leg(m_CamPos, 0.0f, 0.0f, 0.0f, 0.0f);
    	}
    }
    Hexapod :: ~Hexapod()
    {
    	unsigned int i;
    	//for(i = 0; i < 6; i++)	delete m_bein[i];
    	delete[] m_bein;
    }
    

    Änderungen in Leg .h .cpp

    #ifndef LEG_H_CL90
    #define LEG_H_CL90
    
    #include "init_configuration.h"
    #include "iKin_math.h"
    
    class leg
    {
    	public:
    		leg(D3DXVECTOR3* CamPos, float x, float y, float z,  float degAngel);
    		leg(const leg& other);
    		~leg();
    		leg& operator = (const leg& other);
    		...
    
    #include "leg.h"
    
    float leg::m_PI			= 3.141592f;
    float leg::m_length[4]	= {3.29f,	1.5f,	6.78f, 8.07f};
    
    leg :: leg(D3DXVECTOR3* CamPos, float x, float y, float z,  float degAngel)
    {
    	...
    }
    
    leg :: leg(const leg& other)
    {
    
    }
    leg ::~leg()
    {
    	delete m_iKin;
    }
    leg& leg :: operator = (const leg& other)
    {
    	int i;
    	m_iKin			= other.m_iKin;
    	for(i = 0; i < 4; i++)	m_angle[i]			= other.m_angle[i];
    	for(i = 0; i < 6; i++)	m_matTransform[i]	= other.m_matTransform[i];
    	for(i = 0; i < 5; i++)	m_posVec[i]			= other.m_posVec[i];
    	//for(i = 0; i < 5; i++)	m_length[4]			= other.m_length[4];
    	m_Origin		= other.m_Origin;
    	m_Target		= other.m_Target;
    	m_matRot90		= other.m_matRot90;
    	m_matTurn		= other.m_matTurn;
    	m_matDir		= other.m_matDir;
    	m_matSize		= other.m_matSize;
    	m_matAxisSize	= other.m_matAxisSize;
    	m_matTransPos	= other.m_matTransPos;
    	m_matTransSO	= other.m_matTransSO;
    	m_matTransVS	= other.m_matTransVS;
    	m_matTransOS	= other.m_matTransOS;
    	m_matTransUS	= other.m_matTransUS;
    
    	m_CamPos		= other.m_CamPos;
    	return *this;
    }
    


  • cl90 schrieb:

    ich lasse mir durch _CrtDumpMemoryLeaks(); meine Leeks anzeigen.

    leak = Leck / undichte Stelle
    leek = Lauch / Porree



  • DirkB schrieb:

    cl90 schrieb:

    ich lasse mir durch _CrtDumpMemoryLeaks(); meine Leeks anzeigen.

    leak = Leck / undichte Stelle
    leek = Lauch / Porree

    danke 😞



  • Dir scheinen Grundsätzlich noch ein paar Grundkenntnisse zu fehlen. Ein standard Konstruktor ist ein Konstruktor der keine Argumente benötigt weil er entweder keine Argumente nimmt oder alle Argumente mit default Werten belegt sind.

    Füe leg bedeutet das entweder:

    leg(D3DXVECTOR3* CamPos = nullptr, float x = 0.0f, float y = 0.0f, float z = 0.0f,  float degAngel = 0.0f)
    

    oder

    leg()
    

    Außerdem muß das delete[] aus dem Destruktor von Hexapod weg.

    Wenn du willst das Hexapod einzigartig bleibt würde ich dir empfehlen den Copy Konstruktor und den Copy Operator ins private zu setzen oder als delete zu markieren (falls dein Compiler das schon kann). Beim Move Construktor und Move Operator kannst dus dir ja überlegen.



  • Xebov schrieb:

    Dir scheinen Grundsätzlich noch ein paar Grundkenntnisse zu fehlen.

    Seh ich genauso. Für mich heisst das:

    std::vector<bein> m_bein;
    

    Konstruktoren mit nichtssagenden (und im Fall von campos auch ungültigen) Defaultwerten zu belegen halte ich für wenig sinnvoll.



  • thbadr schrieb:

    Für mich heisst das:

    std::vector<bein> m_bein;
    

    Konstruktoren mit nichtssagenden (und im Fall von campos auch ungültigen) Defaultwerten zu belegen halte ich für wenig sinnvoll.

    Ich stimme dir da absolut zu. Die 2 Beispiele dienten nur zu Illustrierung was sein Fehler bedeutet.



  • Es sind eindeutig Grundlagenprobleme.
    In der Uni wurd uns sowas nur in spärlichster Form beigebracht. Da ging es nur um Algorythmen und Datenstrukturen. Für die ganzen sachen wie STL und Classes gabs 2 Vorlesungen zur einführung. Dementsprechend ist es da bei mir auch sehr dünn.
    Ich mache dieses Projekt a) weil ich meine Grundkenntnisse verbesseren will, aber Vorallem weil dahinter ein komplexes Projekt steht das mich sehr interessiert.

    Welchen Vorteil hat es m_bein in einen Vektor zu schreiben? Ich will ihn weder sortieren noch etwas nachträglich daran ändern.

    warum braucht leg einen standard konstruktor? rufe ich nicht immer meine eigenen auf?

    zum erstellen von Leg in Hexapod:
    Wenn ich in meinem .h file stehen habe: leg m_bein[6]; und angenommen mein Konrstuktor ist leer. wird beim erstellen meines Objektes Hexapod 6 mal sizeof leg im speicher reserviert? gleiche frage zu leg*.

    Was genau passiert wenn ich folgende zeile nutze:

    leg* m_bein;
    m_bein = new leg(m_CamPos, 0.0f, 0.0f, 0.0f, 0.0f);
    

    gebe ich damit meinem pointer m_bein nicht einfach einen Pointer auf ein gerade erzeugtes objekt leg? warum funktioniert das delete dann nicht?

    Warum muss ich den Koppierkonstruktor erstellen, wenn ich eigentlich nur den Zuweisungsoperator in folgendem fall nutze:

    leg m_bein;
    m_bein = leg(m_CamPos, 0.0f, 0.0f, 0.0f, 0.0f);
    

    @Xebov Danke für die tipps mit Hexapod. Ich werde das dann private setzen. ist einfach schöner denke ich. Derzeitig Programmiere ich noch ganz alleine an dem Programm, daher musste ich mir noch nicht so viele gedanken machen was man wie falsch nutzen könnte. Diese Denke muss ich mir noch angewöhnen.



  • cl90 schrieb:

    Welchen Vorteil hat es m_bein in einen Vektor zu schreiben? Ich will ihn weder sortieren noch etwas nachträglich daran ändern.

    Die Meinung gefällt mir. Ich gebe zu, ein Vektor hat hier etwas Overhead. Das optimalste ist hier ein statisches Array von Beinen (lässt sich aber nicht ganz trivial befüllen).

    Aber der Overhead von vector hält sich in Grenzen und ist kleiner als bei deinem Pointer-Array. Denn der Vorteil ist, dass du keinen Standardkonstruktor von leg benötigst:

    class Hexapod {
    public:
        Hexapod(D3DXVECTOR3* CamPos)
          : m_CamPos(CamPos),
            m_bein(6, leg(CamPos, 0.0f, 0.0f, 0.0f, 0.0f)) {}
    
        leg& get_leg(int number) { return m_bein[number]; }
    
    private:
        std::vector<leg> m_bein;
        D3DXVECTOR3*     m_CamPos;
    };
    

    Und das beste: Die Klasse ist so vollständig. Du brauchst keinen Destruktor und keinen operator=, weil das vector für dich erledigt. Und weil die Funktionen so simpel sind, kann man sie auch gleich im Header definieren.



  • oh das ist tatsächlich ziemlich cool.
    ich wusste nicht das vector so viel macht. Haben die anderen STL elemente auch so coole eigenschaften?

    ich muss das mit dem vektor erstmal ausprobieren...



  • cl90 schrieb:

    warum braucht leg einen standard konstruktor? rufe ich nicht immer meine eigenen auf?

    Sobald du einen eigenen Konstruktor einbaust bekommst du den standard Konstruktor nichtmehr automatisch. Deswegen ja auch deine Fehlermeldung.

    cl90 schrieb:

    zum erstellen von Leg in Hexapod:
    Wenn ich in meinem .h file stehen habe: leg m_bein[6]; und angenommen mein Konrstuktor ist leer. wird beim erstellen meines Objektes Hexapod 6 mal sizeof leg im speicher reserviert?

    Nicht direkt. Es wird erstmald er Speicher für das Array geholt und dann wird auf jedes Element der Konstruktor ausgeführt, selbst dann wenn der Körper leer ist und er eigentlich nichts offensichtliches macht. Vorm Eintritt in den Körper des Konstruktors werden die Member initialisiert, sind es Klassen wird zB deren Konstruktor aufgerufen. Es bildet sich ne Kette die Quasi erstmal alles initalisiert.

    cl90 schrieb:

    leg* m_bein;
    m_bein = new leg(m_CamPos, 0.0f, 0.0f, 0.0f, 0.0f);
    

    gebe ich damit meinem pointer m_bein nicht einfach einen Pointer auf ein gerade erzeugtes objekt leg? warum funktioniert das delete dann nicht?

    delete funktioniert an dieser Stelle,d as muß es ja auch. Mein Kommentar bezog sich darauf das du versucht hast ein statisches Array mit delete[] zu löschen, was natürlich nicht geht.

    [quote="cl90"]
    Warum muss ich den Koppierkonstruktor erstellen, wenn ich eigentlich nur den Zuweisungsoperator in folgendem fall nutze:

    leg m_bein;
    m_bein = leg(m_CamPos, 0.0f, 0.0f, 0.0f, 0.0f);
    

    Kopierkonstruktoren und Kopieroperatoren gehen imemr Hand in Hand, hat man das eine benötigt man oft auch das andere. thbadr's Beispiel braucht zb einen CopyKonstruktor.

    Die Lösung mit dem wenigsten Overkill wäre meiner Meinung nach die

    SmartPointer<leg> m_beine[6];
    

    Dort müsste man zwar im Konstruktor selbst tätig werden, dafür hat man aber die selben Annehmlichkeiten wie beim std::vector.

    Noch etwas zu den Pointern die du rumreichst. Wenn du soetwas tust musst du vom Design her garantieren können das der Besitzer des Speicherbereichs erst zerstört wird nachdem alle die den Speicherbereich nutzen zerstört wurden, sonst krachts irgendwann richtig böse.


Anmelden zum Antworten