unique_ptr und Lebenszeit
-
dot schrieb:
Und wie findest du mit deinem Handle raus ob das referenzierte Objekt noch existiert?
Dabei handelt es sich um ein lösbares Problem, bei entsprechenden Rahmenbedingungen.
In den Systemen die ich kenne gibt es einebool isValid() const;mit der man die Gültigkeit des Objekts abfragen kann.
-
Würde es nicht reichen einen Zähler einzuführen, der die Anzahl der unique_weak_ptrs speichert (im Konstruktor der weak_unique_ptrs + 1, im Destruktor -1) und dann dem unique_ptr eine eigene Deleter mitzugeben, der eine Exception schmeist wenn der Zähler nicht null ist? Man könnte die unique_weak_ptr auch noch in einer List speichern, um herauszufinden, welcher pointer noch darauf zugreift.
-
Also im Prinzip könnte die "Container"-Klasse auch Handles rausgeben.
Aber ich gehe ja auch zum Herd und drehe am Knopf (naja, bei den neumodischen Teilen drücke ich), und sag dem Herd nicht "Drehen" während ich auf den offen sichtbaren Knopf deute.
Wenn der Herd aber über Nacht geklaut und durch eine Atombombe mit einem Knopf an derselben Stelle ersetzt wird, dann drücke ich ja auch nicht mehr drauf, selbst wenn nach einer von dem Actionfilm abhängigen Zeit darauf aufmerksam gemacht würde, dass da was falsch lief. (Ich komme gerade vom Herd ;))@Phyax: Genau soetwas habe ich mir vorgestellt und bin noch am überlegen, ob ich mir das mal ausarbeite. Im Moment diskutiere ich hier erstmal nur mit

-
Um was für einen Container geht es denn genau? Ich fürchte ohne konkrete Info kommen wir da nicht weiter...
-
Decimad schrieb:
Also im Prinzip könnte die "Container"-Klasse auch Handles rausgeben.
Genau das, damit bleibt der physikalische Besitz immer an dieser Stelle und "von außen" kann man als unique_ptr drauf zu greifen.
-
Es handelt sich hierbei um die Basisklasse der Knoten sowie den Asssoziationen zwischen allem im Datenmodell meines datenflussorientierten Messprogramms. Sowas wie Labview für Arme (oder sollte man sagen für noch ärmere?). Funktioniert inzwischen auch toll!
Diese Knoten haben eine variable und vor allem dynamische Anzahl von Ein- und Ausgängen, welche von abgelittenen Klassen über die Basisklasse nach draußen veröffentlicht werden. Sie werden in einer Graph-Objekt aggregiert, welches auch die Verbindungen zwischen Ein- und Ausgängen verwaltet und alle Datenstrukturen up-to-date hält. Dieses Datenmodell visualisiert der Graph-View, der nach dem Observer-Muster synchron zum Modell bleibt. Mithilfe von Command-Objekten wird Einfluss auf das Modell genommen (Knoten erzeugen, löschen, bewegen, Verbindungen ziehen usw.).
Während die Datenstrukturen und Klassenaufteilungen noch gewissermaßen im Fluss waren, habe ich bei gewissen Änderungen und Anpassungen einfach nicht die Regeln bezüglich der Lebenszeiten der einzelnen miteinander assoziierten Objekte beachtet, Observer-Benachrichtigungen vergessen, die ich mir zuvor überlegt habe oder ähnliches.Die schwer nachzuvollziehbaren Abstürze traten dann zumeist bei irgendwelchen Windows-Nachrichten-Einsprüngen auf, die Windows bei zB. leerer Warteschlangen durchführt. Dem Debugger fehlt dann der komplette Kontext, der diesen Nachrichtenaufruf auslöste, falls es denn überhaupt einen gibt. Der Fehler (Erzeugung einer inkosistenten Datenstruktur) aber wurde natürlich im logischen Sinne begangen, noch bevor der Prozess sich schlafen gelegt hat, zu dem der Kontext noch 1A klar war. Diesen Zeitpunkt möchte ich erwischen und er auch mich.
-
Nurf, ich stelle mir unter den Namen "Handle" nun aber sowas vor, was Windows rausgibt. Also irgendeine für mich untypisierte Zahl (sind wohl eher verkappte Zeiger), die ich bei Prozeduralen Zugriffen als Argument mit angebe.
Wenn du Handles in einem anderen, mir gelegeneren, Sinn verstehst (Denn solche Aufrufe wie "node->GetOutputName(outputHandle)" oder noch extremer "graph.GetNodeOutputName(outputHandle)" möchte ich nicht haben), dann würde ich dich bitten, mir einmal Pseudo-Code zu bieten oder eine genaurere Beschreibung, damit wir uns hier über dasselbe unterhalten.
-
Ziel ist also das Design zu verbessern oder die Abstürze zu finden?
Handle deswegen, weil es kein Raw-Pointer ist und ein Safety Lookup dazwischen hängt.
-
Na meine automatisierte Bedienung kann inzwischen stundenlang das Programm zufällig bedienen, ohne das irgendetwas leakt oder abstürzt. Ich würde nur gerne das nächste Mal weniger Mühe haben, Fehler wie die beschriebenen einzugrenzen. Das ginge genau mit dem Ansatz, zu dem ich eingangs des Threads eine Implementierung suchte.
Ich möchte solche Windows-"Handles" (Also so wie sie mit der alten C-Api umgesetzt sind) weder retrofitten noch sonstwie einbauen, eher auch zukünftig nicht, da ich mit Objekten so arbeiten möchte, wie ich es mir auch bildlich in der Welt vorstelle (siehe den Herd-Absatz, welcher durchaus nicht nur witzhaft gemeint war).Daher interpretiere den Begriff "Debug-Handle" für mich in diesem Zusammenhang als Smartpointer A auf ein Objekt, dessen Lebenszeit von einem anderen Smartpointer B verwaltet wird. B weiß, wieviele Handles vom Typ A auf seine Ressource draußen sind, kann optional schmeißen (zB. als Debugmöglichkeit für Pointer-Zeug hinter eine schnittstelle) falls er zerstört wird, während noch Handles draußen sind.
Falls B nicht schmeißen soll, soll A im Debug-Modus die die Gültigkeit überprüfen vor einer Dereferenzierung. Im Release-Build soll A dann wie ein unique_ptr funktionieren und B ein blanker Zeiger sein.
Diese beschriebene Funktionalität des Handles könnte man natürlich bestimmt auch in Release-Builds irgendwie verwenden, aber das ist nicht mein Anliegen.Da das jetzt schon verteilt über einige Zeit so in dem Thread erwähnt wurde, aber niemand eine existierende Implementierung vorschlug, gehe ich davon aus, dass ich mich dieser Sache dann selber annehmen muss

-
Wenn der Herd aber über Nacht geklaut und durch eine Atombombe mit einem Knopf an derselben Stelle ersetzt wird
Und sowas passiert dir oefters und unabsichtlich? Bitte hoere auf zu programmieren.

-
Ja, du glaubst nicht, wie verstrahlt ich ab und zu rumlaufe
Aber heißt doch "das Recht auf Programmieren ist unantastbar" oder so ähnlich!
-
Decimad schrieb:
Falls B nicht schmeißen soll, soll A im Debug-Modus die die Gültigkeit überprüfen vor einer Dereferenzierung. Im Release-Build soll A dann wie ein unique_ptr funktionieren und B ein blanker Zeiger sein.
...
Da das jetzt schon verteilt über einige Zeit so in dem Thread erwähnt wurde, aber niemand eine existierende Implementierung vorschlug, gehe ich davon aus, dass ich mich dieser Sache dann selber annehmen muss
1. Ja das ist trivial und für den Release-Build stehen halt #ifdefs drumherum und der Compiler optimiert die leere Check-Funktion dann weg.
2. Für den geübten Cpp-Programmierer mit CRTP im Nu geschrieben.
Allerdings hast du immer noch nicht meinen Ansatz verstanden. Wenn du den Herd nie besitzt, kann ihn dir auch niemand klauen.
Er ist nur geliehen und der echte Besitzer kann ihn dir immer wegnehmen.
Aber vor deinen Freunden kannst du immer noch so tun, als würde er dir gehören.