shared_ptr - Delete?



  • Hey 🙂

    Muss ich shared_ptr am ende meines Programms löschen?
    also z.b. Hier in diesem stark vereinfachtem Programm:

    int main()
    {
    	shared_ptr<Hexapod>	hexa	= shared_ptr<Hexapod>	(new Hexapod(data));
    	shared_ptr<GUI3D>	gui		= shared_ptr<GUI3D>		(new GUI3D(data));
    	shared_ptr<Console>	cons	= shared_ptr<Console>	(new Console(data));
    	shared_ptr<Control>	ctrl	= shared_ptr<Control>	(new Control(data, hexa, cons));
    
    	while(!data->KillThisProcess())
        {
    		//	loopThatShit
        }
    
    	_CrtDumpMemoryLeaks();
    
    	return EXIT_SUCCESS;
    }
    


  • Nein, dafür ist der shared_ptr zuständig.
    Wenn nur ein Objekt Besitzer sein soll, bietet sich aber eher der unique_ptr an.
    Und schaue dir mal make_shared und auto an.





  • In deinem konkreten Beispiel solltest du dir allerdings wohl sowieso überlegen, wieso du die Objekte nicht einfach am Stack anlegst... 😉



  • Nein.

    Und warum steht da nicht einfach

    int main()
    {
            Hexapod hexa(data);
            GUI3D   gui (data);
            Console cons(data);
            Control ctrl(data, &hexa, &cons);
    
            while(!data->KillThisProcess())
            {
                //  loopThatShit
            }
            return EXIT_SUCCESS;
    }
    


  • krümelkacker schrieb:

    Nein.

    Und warum steht da nicht einfach

    int main()
    {
            Hexapod hexa(data);
            GUI3D   gui (data);
            Console cons(data);
            Control ctrl(data, &hexa, &cons);
    
            while(!data->KillThisProcess())
            {
                //  loopThatShit
            }
            return EXIT_SUCCESS;
    }
    

    Genau so war es vorher. Ich bin nur gerade auf der suche nach Leaks..

    In der loop werden Dinge ausgeführt die diese und zwei weitere Klassen die hier nicht aufgelistet sind, selbst ausführen... Alles in allem hat das Projekt 8000 zeilen Code mit vielen SubKlassen etc.

    Mein Problem ist nun das ich viele Leaks habe.
    Denn ich habe damals als ich angefangen habe zu programmieren noch nicht so sehr drauf geachtet.



  • cl90 schrieb:

    Genau so war es vorher. Ich bin nur gerade auf der suche nach Leaks..

    Und die findest du am besten, indem du noch öfter new benutzt!?



  • nja wenn der shared_ptr das regelt geht das doch eher in ordnung als wenn ich raw pointer um mich werfe.



  • Du brauchst aber keine raw pointer, machs einfach so wie krümelkacker es gesagt hat.
    Dabei können gar keine Leaks entstehen.



  • cl90 schrieb:

    Genau so war es vorher. Ich bin nur gerade auf der suche nach Leaks..

    löl, YMMD!



  • manchmal seid ihr hier echt ein bisschen unfair.
    Ja schön, wirkt wirklich ziemlich naiv, new/Delete-fehler durch noch mehr new's zu beheben, aber das ist kein Grund hier so am Rad zu drehen.
    Zumal wenn ich das richtig verstanden habe, es keinen Unterschied macht, weil die shared_ptr sicher nicht anfangen zu leaken.



  • Doch, eine Fehlerquelle gibt es:

    some_func(shared_ptr<Foo>(new Foo()), shared_ptr<Bar>(new Bar()), func());
    

    Hier kann es passieren, dass erst 2x new aufgerufen wird (bzw. einmal new + Konstrukotor, dann das nächste), aber die Speicheradressen werden noch nicht an den shared_ptr gekettet. Wirft jetzt der zweite Konstruktor oder die func()-Funktion eine Exception, dann hast du dein Leak.

    some_func(make_shared<Foo>(), make_shared<Bar>(), func());
    

    Hat das Problem nicht mehr.



  • cl90 schrieb:

    Zumal wenn ich das richtig verstanden habe, es keinen Unterschied macht, weil die shared_ptr sicher nicht anfangen zu leaken.

    Es stimmt, dass hared_ptr recht sicher sind. Das ändert aber nichts daran, dass es Blödsinn ist Objekte dynamisch zu erstellen, wenn das nicht nötig ist. Das ganze ist langsamer, unkomfortabler und du handelst dir unnötige Indirektionen ein. Am besten sowas gar nicht erst angewöhnen.



  • Skym0sh0 schrieb:

    Doch, eine Fehlerquelle gibt es:

    some_func(shared_ptr<Foo>(new Foo()), shared_ptr<Bar>(new Bar()), func());
    

    also wird sowas hier vermutlich auch probleme machen oder?

    m_Commands.insert(_Command("set_screen_width",			shared_ptr<_IStrategy>(new _cmdScreenWith()),	shared_ptr<_IStrategyVal>(new _valScreenWidth())));
    

    TNA schrieb:

    Am besten sowas gar nicht erst angewöhnen.

    Ok, Ich habe vorher mit Raw Pointer gearbeitet. Mir wurde nur abgeraten das weiter zu machen.
    So wie ich das mitbekommen habe war ein oder mehrere smart pointer nur in den neuen c++ standarts vorhanden.
    Was gäbe es denn für alternativen?

    Ich vermeide Call by Value immer wenn irgendetwas übergeben wird das größer ist als 4 byte. Ich habe mir in vielen fällen das "const&" angewöhnt. Aber gerade bei Dingen wie Datenklassen die an jede klasse weiter gereicht werden, kam mir das shared_ptr Konzept sinvoll vor.

    edit:
    bzw wenn ich eine lösung für folgendes problem bekomme würde ich sehr viel new spaaren:

    Wie kann ich in folgendem Code, die erstellung von m_iKin ohne irgendein new schreiben? Bemerkung: Der Konstruktor von iKin bekommt mehrere Parameter.

    class leg : public Observer		
    {								
    	private:					
    		shared_ptr<iKin_math>	m_iKin;
    };
    
    leg :: leg()
    {
    	m_iKin		= shared_ptr<iKin_math>(new iKin_math(...Vars...));
    }
    


  • cl90 schrieb:

    Wie kann ich in folgendem Code, die erstellung von m_iKin ohne irgendein new schreiben?

    class leg : public Observer		
    {								
      private:					
        iKin_math	m_iKin;
    };
    
    leg :: leg()
    : m_iKin(...Vars...)
    {
    }
    


  • ah 😑
    da war ja sowas wie eine initialisierungsliste... jetzt wo der Wink mit dem Zaunpfahl kommt errinnere ich mich.

    danke dir!



  • Ich verstehe nicht, wieso Du immer mit Raw-Pointer argumentierst, wenn man Dir von shared_ptr abrät. Weißt Du nicht, dass es in C++ automatische Objekte gibt wie in krümelkackers Code vorgestellt? Das ist weder Raw- noch Smart-Pointer. Wenn das Beispiel nur irgendwie illustriert ist und gar nicht den eigentlichen Code widerspiegelt, okay. Aber in dem Beispiel sind weder Raw-Pointer noch Smart-Pointers empfehlenswert.

    Ich habe mir in vielen fällen das "const&" angewöhnt. Aber gerade bei Dingen wie Datenklassen die an jede klasse weiter gereicht werden, kam mir das shared_ptr Konzept sinvoll vor.

    "Ich fahre eigentlich gern mit dem Auto zur Arbeit, aber für die Uni erschien es mir besser die schwarze Hose zu tragen."

    shared_ptr sind dazu gedacht Besitzverhältnisse zu klären, geteilte nämlich. Die werden nicht genutzt, um die Übergabe an Funktionen/Klassen anders zu handhaben. Einer Klasse, die einen Verweis (ohne Besitzmacht!) über ein Objekt benötigt, einen Raw-Pointer zu übergeben, ist in Ordnung. An dieser Stelle geht es aber auch nicht um Besitz, denn die Klasse, welche das Argument erhält, muss sich ja nicht um new/delete/Speicherverwaltung kümmern.

    Der Unterschied mag fein erscheinen, es ist aber wichtig sich darüber Gedanken zu machen, ob geteilter Besitz wirklich notwendig ist (und das ist eben fast nie der Fall). Wenn viele unterschiedliche Klassen ein Objekt nutzen, heißt das nicht, dass die das auch besitzen müssen.

    da war ja sowas wie eine initialisierungsliste...

    Das ist aber nicht der Punkt. Automatisches Objekt auf dem Stack wird hier genutzt, während Dein Code ein Objekt auf dem Heap (über new) abgelegt hat. Die Initialisierungsliste kannst Du auch nutzen, um letzteres zu erzeugen.

    Entweder lassen sich in Deinem Denken noch einige Dinge verbessern oder es liegt nur am Ausdruck Deiner Argumente. Jedenfalls gibt es da was zu tun. 🙂



  • Eisflamme schrieb:

    Jedenfalls gibt es da was zu tun. 🙂

    Das ist der Plan. Das programm läuft Absturzsicher und macht keine Probleme, nur ich will a) die Leaks loswerden denn das kann vermutlich zu einem Problem werden, und b) "unsauberen" code durch "besseren" ersetzen.

    Den Ansatz das raw pointer schlecht sind hab ich mitlerweile verworfen.

    Ich werd hier nochmal alles durchlesen und versuchen alle Tipps anzuwenden.



  • cl90 schrieb:

    Ok, Ich habe vorher mit Raw Pointer gearbeitet. Mir wurde nur abgeraten das weiter zu machen.

    Das Problem sind nicht die Raw-Pointer, das Problem sind Raw-Pointer in Verbindung mit new . Denn bei denen musst du manuell delete aufrufen. Raw-Pointer, die auf ein Objekt zeigen, welches an anderer Stelle verwaltet wird (z.B. durch Smart-Pointer, oder weil es auf dem Stack liegt) sind kein Problem.



  • Das Problem ist, das man hier Anfängern shared_ptr und Konsorten um die Ohren haut, bevor sie überhaupt verstanden haben, was das Problem ist.


Anmelden zum Antworten