AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls Delphi sporadische Exception beim Freigeben von TLabels
Thema durchsuchen
Ansicht
Themen-Optionen

sporadische Exception beim Freigeben von TLabels

Ein Thema von Gausi · begonnen am 27. Dez 2022 · letzter Beitrag vom 4. Jan 2023
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von Gausi
Gausi

Registriert seit: 17. Jul 2005
847 Beiträge
 
Delphi 11 Alexandria
 
#1

sporadische Exception beim Freigeben von TLabels

  Alt 27. Dez 2022, 14:27
Für die Anzeige einer relativ kurzen Liste von Objekt-Eigenschaften nutze ich dynamisch erzeugte TLabels. Diese verwalte ich in einer TObjectList mit OwnsObjects = True. Die Anzeige erledigt eine Methode "CreateTagLabels", die im Wesentlichen so aussieht:
Delphi-Quellcode:
TagLabelList.Clear; // Alte Labels freigeben
// neue erstellen
for i := 0 to Count-1 do begin
  newLabel := TLabel.Create(Nil); // Kein Owner, das ist ja die ObjectList
  TagLabelList.Add(newLabel);
  newLabel.Parent := Panel1;
  // newLabel.Caption := ...; Top, Left, OnClick, usw. usf.
end;
Und das knallt gelegentlich beim "Clear". Bei mir bisher gar nicht, aber ein Nutzer hat mir jetzt diesen Bugreport 2x zugeschickt. Einmal lief das Programm 2 Tage, beim nächsten Mal 8 Tage.

Der Callstack von MadExcept (gekürzt) sieht so aus.
Code:
exception message : Zugriffsverletzung bei Adresse 0066CD01 in Modul 'nemp.exe'. Lesen von Adresse 00000008.

main thread ($57e8):
Vcl.Controls           AlignNestedControls
Vcl.Controls           TWinControl.AlignControls
Vcl.Controls           TWinControl.AlignControl
Vcl.Controls           TWinControl.RemoveControl
Vcl.Controls           TControl.SetParent
Vcl.Controls           TControl.Destroy
madExcept              InterceptClassDestroy
Vcl.Controls           TControlCanvas.Destroy
System        1191  +0 TObject.Free
System.Contnrs         TObjectList.Notify
System.Classes         TList.SetCount
System.Classes         TList.Clear
NempMainUnit  5703  +2 TNemp_MainForm.CreateTagLabels
Das sieht für mich so aus, als würde das Parent-Panel versuchen, während des Freigebens der Label-Liste nochmal auf Objekte zuzugreifen, die die ObjectList schon freigegeben hat.
So wie ich den VCL-Code verstehe, sollte das aber eigentlich nicht passieren: Die Objekte in der Liste werden beim Clear der Reihe nach freigegeben, jedes einzelne benachrichtigt sein Parent darüber, welches das Control dann "vergisst". Beim nächsten Label.Free; sollte das vorherige dann im Parent verschwunden sein. Oder kann es in seltenen Fällen dazu kommen, dass sich da irgendwelche internen Messages überschneiden?
The angels have the phone box.
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.171 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: sporadische Exception beim Freigeben von TLabels

  Alt 27. Dez 2022, 15:39
Du nutzt aber nicht Threads beim erzeugen/freigeben?
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.351 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: sporadische Exception beim Freigeben von TLabels

  Alt 27. Dez 2022, 15:52
Ich würde dir raten, das Projekt mit FastMM zu kompilieren. Wenn ich es im FullDebugMode damit ausführe, bekomme ich sofort z.B. beim Beenden Fehlermeldungen, dass da Objekte doppelt freigegeben werden. Die passenden Stacktraces (vom Erzeugen, Freigeben und dem fehlerhaften Zugriff) zeigt dir FastMM auch.

Das war auch meine Idee, weshalb ich FastMM überhaupt drauf angesetzt hatte.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.152 Beiträge
 
Delphi 12 Athens
 
#4

AW: sporadische Exception beim Freigeben von TLabels

  Alt 27. Dez 2022, 15:59
Ja, erstmal keine Threads.

Und dann ist eine TComponentList besser, als eine TObjectList.
Oder einfach ein TComponent als Container/Liste. (weil Delphi leider Ersteres hat, aber mal wieder nicht öffentlich und man es daher selber bauen muß)
Bzw. ein Owner-Objekt nutzen und dann statt TagLabelList.Clear diesen Owner freigeben und einen Neuen erstellen.



Wo sind denn die Labels drauf?
Das wird nicht zufällig freigegeben, bevor du deine TagLabelList leer machst?

Genau dafür ist eine ComponentList, denn dort löscht das Label sich selbst raus, wenn es von jemand Anderem freigegeben würde.


Zitat:
Das sieht für mich so aus, als würde das Parent-Panel versuchen, während des Freigebens der Label-Liste nochmal auf Objekte zuzugreifen
Zitat:
Das wird nicht zufällig freigegeben, bevor du deine TagLabelList leer machst?
Nicht nochmal, sondern vorher ja immer.

Nicht nur der Owner gibt etwas frei, sondern auch der Parent.
Ist ein krankes Verhalten, was die VCL leider von der GDI übernommen hat (dort gibt es keine expliziten Owner, sonden nur einen Parent, der Alles macht),
obwohl es garnicht nötig gewesen wäre, weil die WinControls auch überleben können, selbst wenn das innere HWND und DC noch nicht mehr existiert.


TComponents haben aber ein intenes Notifications-Systen, womit man sich informieren lassen kannt, wenn es freigegeben wird. (das nutzt der Owner, Parent und z.B. eine ComponentList)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (27. Dez 2022 um 16:09 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Gausi
Gausi

Registriert seit: 17. Jul 2005
847 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: sporadische Exception beim Freigeben von TLabels

  Alt 27. Dez 2022, 17:02
Danke schonmal für die Antworten.

Nein, Threads habe ich an der Stelle nicht. Ich klicke auf ein Element in einer VirtualTreeView, und zeige im "onClick" die Elementeigenschaften an. Ein Teil davon ist das Erzeugen dieser Labels. Ich nutze zwar durchaus mehrere Threads für einige Hintergrundarbeiten, aber die Labels sind rein VCL-Thread. das würde auch öfter knallen, denke ich.

FastMM habe ich mal probiert (du meinst doch das hier, oder? https://github.com/pleriche/FastMM4). Tatsächlich zeigt der mir am Ende an, dass etwas doppelt freigegeben wird, aber das hat hiermit nichts zu tun - da gibt es noch ein Problemchen im Finalize einer Unit. Wenn ich das (erstmal Quick&Dirty, so ganz gefällt mir die Lösung noch nicht) ins OnDestroy der MainForm verschiebe, gibt es keine solche Meldung mehr.

Die Label liegen auf einem Panel (bzw. auf einer eigenen Ableitung davon). Dieses Panel bleibt aber zur Laufzeit erhalten. Die Objekte in der Liste sollten also nicht "von außen" gelöscht werden können. Die TComponentList schaue ich mir aber auch nochmal an. Ob dadurch der Fehler behoben wird, kann ich aber ohne Reproduktionsweg nicht so richtig testen ...

TComponents haben aber ein intenes Notifications-Systen, womit man sich informieren lassen kann, wenn es freigegeben wird. (das nutzt der Owner, Parent und z.B. eine ComponentList)
Jep, das wird hier ja auch getriggert. Durch das Clear der ObjectList wird für jedes Objekt (=TLabel), das jetzt zerstört werden soll, das Parent informiert. Das Parent löscht die Referenz darauf, und ruft dann noch AlignControls auf (auch wenn das hier nicht nötig wäre, da die Labels alle alNone sind). Und dabei kommt die Exception. Meine Vermutung war also, dass das Parent doch noch Referenzen auf Objekte hat, die die Liste schon fertig zerstört hat. Aber das sollte nicht passieren, wenn ich mir den Code von TObjectList.Clear so anschaue und von all dem Gedöns, was da dranhängt ...
The angels have the phone box.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.020 Beiträge
 
Delphi 12 Athens
 
#6

AW: sporadische Exception beim Freigeben von TLabels

  Alt 27. Dez 2022, 17:11
Du könntest das Clear in ein DisableAlign/EnableAlign des Panels kapseln.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.152 Beiträge
 
Delphi 12 Athens
 
#7

AW: sporadische Exception beim Freigeben von TLabels

  Alt 27. Dez 2022, 18:12
Ansonsten bliebe noch dieses grauenhafte DebugDCUs wieder zu aktivieren und zu hoffen dann mehr sehen zu können.

Das Einzige, was wie ein "Offset" von 8 ausssieht, welches ich auf die Schnelle sah, wäre ResizeList.Capacity, bzw. das FCapacity.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (27. Dez 2022 um 18:27 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Gausi
Gausi

Registriert seit: 17. Jul 2005
847 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: sporadische Exception beim Freigeben von TLabels

  Alt 28. Dez 2022, 13:26
Du könntest das Clear in ein DisableAlign/EnableAlign des Panels kapseln.
Ah, so heißt das. Ich hatte BeginUpdate/EndUpdate probiert, aber das gibt es bei Panels ja nicht.

Ich habe jetzt die Liste zu einer TComponentList gemacht (weitere Änderungen neben der Deklaration und dem Create scheinen nicht nötig zu sein), und das Clear gekapselt wie Uwe es vorgeschlagen hat. Das sollte reichen. Falls nicht, muss ich später nochmal genauer schauen ...
The angels have the phone box.
  Mit Zitat antworten Zitat
TigerLilly

Registriert seit: 24. Mai 2017
Ort: Wien, Österreich
1.175 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: sporadische Exception beim Freigeben von TLabels

  Alt 29. Dez 2022, 07:11
Möglicherweise führt das Freigeben des Labels zu einer Aktualisierung des Parents der noch nicht weiß, dass der Label freigegeben ist? Siehe auch Post von Uwe Raabe.
  Mit Zitat antworten Zitat
Benutzerbild von ConnorMcLeod
ConnorMcLeod

Registriert seit: 13. Okt 2010
Ort: Bayern
490 Beiträge
 
Delphi 10.4 Sydney
 
#10

AW: sporadische Exception beim Freigeben von TLabels

  Alt 29. Dez 2022, 22:50
Mglw ist FreeNotification Dein Freund.
Nr.1 Delphi-Tool: [F7]
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:18 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz