![]() |
sporadische Exception beim Freigeben von TLabels
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:
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.
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; Der Callstack von MadExcept (gekürzt) sieht so aus.
Code:
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.
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 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? |
AW: sporadische Exception beim Freigeben von TLabels
Du nutzt aber nicht Threads beim erzeugen/freigeben?
|
AW: sporadische Exception beim Freigeben von TLabels
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. |
AW: sporadische Exception beim Freigeben von TLabels
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:
Zitat:
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) |
AW: sporadische Exception beim Freigeben von TLabels
Danke schonmal für die Antworten. :thumb:
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. :lol: FastMM habe ich mal probiert (du meinst doch das hier, oder? ![]() 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 ... :stupid: Zitat:
|
AW: sporadische Exception beim Freigeben von TLabels
Du könntest das Clear in ein DisableAlign/EnableAlign des Panels kapseln.
|
AW: sporadische Exception beim Freigeben von TLabels
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. |
AW: sporadische Exception beim Freigeben von TLabels
Zitat:
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 ... |
AW: sporadische Exception beim Freigeben von TLabels
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.
|
AW: sporadische Exception beim Freigeben von TLabels
Mglw ist FreeNotification Dein Freund.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:48 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz