Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

11

22.06.2014, 21:04

Du verwendest ihn als normale Variable und genauso wird er dann auch mit Abschluss des Programmes oder der Funktion (whatever) wieder freigegeben.
Wenn du natürlich Zeiger auf shared_ptr hast sieht das evt. anders aus...

Evrey

Treue Seele

Beiträge: 245

Beruf: Weltherrscher

  • Private Nachricht senden

12

22.06.2014, 21:22

Stichwort RAII. Der Destruktor kümmert sich ums Aufräumen. Overhead hat ein std::shared_ptr eigentlich nur beim Kopieren und Löschen. Beachte allerdings Zirkelschlüsse.

C-/C++-Quelltext

1
2
3
4
int main(int _argc, char** _argv) noexcept {
  asm volatile("lock cmpxchg8b %eax");
  return 0;
} // ::main
(Dieses kleine Biest vermochte einst x86-Prozessoren lahm zu legen.)

=> Und er blogt unter Hackish.Codes D:

13

22.06.2014, 21:42

Ich glaube, da war meine Fragestellung zu unpräzise. Ich wollte eigentlich wissen, wie der Destruktor des shared_ptr sicherstellt, dass falls er die Ressource (bspw. dynamisch alloziierter Speicher) löschen soll, diese in JEDEM Fall freigegeben wird. Was macht er also, wenn ein Fehler (Exception) auftritt? Propbiert er es endlos erneut, oder kehrt er einfach zum Aufrufer zurück, und lässt die Ressource in einem ungültigen Zustand zurück? Wie stellt er seine Exception-Garantie sicher? Soweit ich das sehe, bietet er die No-throw-Garantie an, schluckt er also die Exceptions einfach? Wobei bei der No-throw-Garantie ja eigentlich mit dazu gehört, dass die Ressourcen in einem gültigen (und nicht halb gelöschten) Zustand verlassen werden.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

14

22.06.2014, 21:43

Der Nachteil an dieser verteilten Art der Verwaltung durch share_ptr ist der, dass wenn man den Ressourcen-Manager dazu zwingt, dass er alle seine Ressourcen wegwirft, immer noch gültige Ressourcen draußen herumlaufen, die der Manager nicht mehr kennt. Auf den ersten Blick ist das natürlich gut, weil es keine Crashes bei den Objekten gibt, die diese Ressource verwenden. Der Nachteil aber ist, dass der Manager das Objekt erneut in den Speicher lädt, falls er danach gefragt wird und dann die Ressource doppelt im RAM liegt. Oder dreifach. Oder vierfach... je nachdem wie oft man alle Ressourcen freigeben lässt.

Oft heißt es auch, dass eventuell eine Klasse einen share_ptr auf etwas halten muss, was es sonst eigentlich nichts angeht. Z.B. bei der SFML typisch wäre eine Entity, die ein Sprite hat und das Sprite braucht eine gültige Texture. Da das Sprite nur eine einfache Referenz hält, muss die Entity einen share_ptr darauf halten. Aber eigentlich geht die Entity die Texture gar nichts an. Um es ordentlich zu machen müsste man jetzt Sprite wiederum kapseln in... ein Pseudo-Sprite. Irgendwie uncool.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

15

22.06.2014, 21:46

Wenn eine Methode die der Smartpointer aufruft eine Exception wirft wird das Objekt zerstört (grob gesagt), ungefähr so vorstellbar:

C-/C++-Quelltext

1
2
3
4
5
class shared_ptr{
    void operator->(bla){
        try{obj->ka(bla);}catch(...){delete obj;}
    }
}

16

22.06.2014, 21:47

@Blue: Da haben wir uns gerade verpasst ;)

Ja, das sehe ich auch so, d.h. die beste Lösung wäre es eigentlich einen Ressourcen-Manager "frei Haus" mitzuliefern, welcher Handles zurückgibt. Soweit habe ich das bisher auch implementiert. Die Handles können zu Zeigern dereferenziert werden, und wenn sie das tun, dann wird die Ressource erneut geladen, falls sie nicht mehr existiert. Sprites und generell andere Objekte erhalten also im Endeffekt Handles auf die Ressourcen.

@DeKugelschieber: Das ist immer noch nicht, was ich wissen will. Wie stellt der Destruktor sicher, dass die Ressource IN JEDEM FALL gelöscht wird, und nicht halb-gelöscht im Speicher verbleibt? Um das zu verdeutlichen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
class Foo
{
public:

    ~Foo() { throw exception; }
}

/* In std::shared_ptr */
~std::shared_ptr()
{
    delete ptr; // <- Was machen wir jetzt mit der Exception? Eventuell sind Member von Foo noch gar nicht freigegeben worden.
}

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

17

22.06.2014, 21:51

Wie stellst du das denn sicher? 100%ige Garantie gibt es nicht, das letzte Wort kann dann nur noch das OS haben (oder der Mensch per Reset Button).

18

22.06.2014, 21:52

Das heißt, std::shared_ptr kann in seinem Destruktor eine Exception werfen? Das wäre aber äußerst unpraktisch....

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

19

22.06.2014, 21:58

Laut Doku wird ein Delete oder eben delete/delete[] genutzt. Ob er den Fehler schluckt weiß ich nicht.
Wenn dir das nicht zusagt kannst du aber einen eigenen Deleter erstellen. Siehe Doku.

Und ansonsten würde ich sagen: werd nicht paranoid! ;)

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

20

22.06.2014, 21:58

Auch Handles lösen das Problem nicht besser als shared_ptr. Sogar eher im Gegenteil. Ohne einen shared_ptr nützt dir auch das Handle relativ wenig. Sonst wird ja eventuell wieder eine Textur freigegeben, deren Pointer kurz vorher eine Entity erst angefordert hat. Und nun musst du zusätzlich zu dem offensichtlich notwendigen shared_ptr sogar auch noch das Handle halten.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Werbeanzeige