Create and forget: Referenzzählung für Objekte

Zur Vorstellung von Komponenten und Units für Lazarus
Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 168
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Create and forget: Referenzzählung für Objekte

Beitrag von Jorg3000 »

Besten Dank, damit bin ich ja schon recht glücklich!
Dann prüfe ich morgen mal die Sache mit AddRef und mache ein paar Tests, mit const und ohne und als var-Parameter.
Ich meine ich hätte es vorletzte Woche schon getestet und hatte keine Notwendigkeit für AddRef gesehen. Aber ich überprüfe das lieber nochmal.
Grüße, Jörg

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 168
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Create and forget: Referenzzählung für Objekte

Beitrag von Jorg3000 »

Moin again!
AddRef habe ich nun hinzugefügt. Ich hatte ursprünglich die Beschreibung von AddRef im FPC-Wiki falsch verstanden.
Laut meinen Tests wird AddRef und das zugehörige Finalize nur aufgerufen, wenn man einen Record als Wertparameter an eine Prozedure übergibt (also wo kein const/var/out angegeben ist).

Im Quellcode meiner Unit habe ich zudem eine Warnung zum FPC-Bug bei Managed Records hinzugefügt.
So unschön der FPC-Bug auch sein kann, ist es kein Bug meiner Unit, sondern man muss derzeit halt generell aufpassen z.B. keinen Record-Constructor Create zu nutzen, den ich aber nicht verwende.
Weder in meiner Unit noch im Beispielprojekt taucht dies auf und somit auch keine Probleme. Ich könnte den FPC-Bug aber zusätzlich noch irgendwo im Text meiner Webseite erwähnen.

Download-Seite: https://www.html-file.org/pascal/refere ... spiel.html

Ich werde in den nächsten Tagen auch noch eine englische Webseite machen und es dann mal im internationalen Forum posten.
Grüße, Jörg

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Create and forget: Referenzzählung für Objekte

Beitrag von Warf »

Ich kann dir ja mal sagen wie ich den Bug gefunden habe.
Tatsächlich hatte ich damals auch eine Referenzzähler implementierung gebaut, und alles hatte einwandfrei funktioniert. Ein paar Wochen später, nachdem ich in einem Projekt damit schon mehrere tausend Zeilen code geschrieben hatte, hats plötzlich gekracht. Der Grund, ich hatte nen Enumerator record der die Liste als Referenzgezählten pointer bekommen hat und GetEnumerator löst den Bug genauso aus. Natürlich habe ich nicht an die Referenzcounter Implementierung gedacht, weil ich die ja schon seit wochen intensiv genutzt habe und sie hat problemlos funktioniert. Das finden des bugs hat am ende fast 2 tage gedauert (da es an einer ganz anderen Stelle kracht, ist das echt schwer rauszufinden was da schief lief).

Darauf hin habe ich den bug reportet und dachte mir das ich einfach keine Enumerator Records mehr benutzen sollte, das ist zwar nicht schön aber kein Problem (ist halt n bisschen langsamer mit Klassen aber macht für den Nutzer keinen unterschied). Und es hat auch erst mal geklappt. Ein paar Wochen sind weiter ins Land gezogen und es hat plötzlich wieder gekracht, natürlich habe ich wieder mal zu erst nicht an den bug gedacht, denn der war ja nur bei enumeratoren (außerdem war das schon so lange her das ich ihn z.T. wieder vergessen habe). Diesmal war der Grund der Konstruktor, wie bei den Beispielen die ich hier gegeben habe. Das finden davon hat wieder mehr als einen Tag gedauert.

Ich bin also innerhalb von einem Monat 2 mal auf diesen Bug gestolpert, in unterschiedlichen Scenarios, wenn ein Bug in einer bestimmten, sehr speziellen SItuation auftaucht (z.B. nur bei GetEnumerator, da enumeratoren ganz eigen behandelt werden) dann geschenkt, dann ist das wahrscheinlich einfach nur ein Bug für diesen besonderen Fall.
Wenn der Bug aber in verschiedenen situationen auftaucht, wie hier im konstruktor oder Enumerator, dann ist der in irgendeiner unterliegenden Funktion und kann noch öfter auftreten.
Und in meiner Erfahrung ein Bug der 2 mal auftritt wird auch noch ein drittes mal auftreten. Gleichzeitig ist es ziemlich schwer den Bug zu finden wenn er auftritt, und zu dem Zeitpunkt als ich ihn entdeckt hatte hatte ich managed records so viel verwendet das, auch wenn die beiden Situationen (enumerator und konstruktor) relativ einfach zu umgehen sind (auch wenn es natürlich nervt den kompletten code durchzugehen und alle Konstruktoren zu entfernen), wenn der Bug noch einmal wo anders auftritt, wird das wieder mindestens ein tag debugging sein, und dann wahrscheinlich noch größere Rewrites benötigen.
Daher habe ich mich entschieden das das so keinen Sinn macht, und nach mehr als einem Monat und 6 tausend Zeilen Code die ich bereits geschrieben habe, habe ich das Projekt eingestampft.

Bis dieser Bug gefixt wird macht es keinen Sinn Managed records zu verwenden. Dieser Bug tritt immer an ganz anderer Stelle auf, vor allem da ein großteil der Vorkomnisse des Bugs keine Fehler auslösen (wie gesagt ich habe konstruktoren schon für mehr als einen Monat lang benutzt bevor es das erste mal gekracht hat).

Daher einfach nur hinzuschreiben das man keine Konstruktoren verwenden sollte ist m.E. nach nicht ausreichend, weil ich schon mindestens eine andere Situation kenne wo der auftaucht und es wahrscheinlich noch andere situationen gibt die ich noch nicht kenne. Und ich kann aus erster Hand sagen das wenn der Bug auftritt ist er extrem schwer zu finden, und wird wahrscheinlich erst auftreten nachdem man schon so viel code hat der den potentiell triggern kann, das es definitiv größere Änderungen benötigt.

Vor allem, grade für Referenzzählung, brauchst du keine Records, du kannst alles was du mit deinem Record machst auch mit einem Interface machen, was diesen Bug nicht hat. Daher würde ich wirklich empfehlen statt zu hoffen das der Bug nicht auftritt, einfach Interfaces zu benutzen und sicher sein das der Bug nicht auftreten kann.

Ich muss aber zugeben den Bug habe ich glaube ich in Mitte 2019 reportet, also schon 3 Jahre her, hoffnung das der gefixt wird habe ich also nicht wirklich

PascalDragon
Beiträge: 825
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Create and forget: Referenzzählung für Objekte

Beitrag von PascalDragon »

Warf hat geschrieben:
Di 26. Apr 2022, 10:02
Ich muss aber zugeben den Bug habe ich glaube ich in Mitte 2019 reportet, also schon 3 Jahre her, hoffnung das der gefixt wird habe ich also nicht wirklich
Weil das ein verdammt komplexes Problem ist und man im Endeffekt die ganzen Mechanismen für temporäre Variablen von Managed Typen im Compiler umgraben kann (ich habe mir das Problem damals durchaus angeschaut). Da muss man erstmal den Kopf und die Zeit dafür frei haben.
FPC Compiler Entwickler

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Create and forget: Referenzzählung für Objekte

Beitrag von Warf »

Kann ich verstehen, war jetzt auch nicht konfrontativ gemeint, wollte nur sagen das man sich nicht drauf verlassen sollte das das in absehbarer Zeit behoben wird.

Antworten