Autor |
Beitrag |
Peter18
Beiträge: 489
Erhaltene Danke: 2
Delphi4
|
Verfasst: Mo 02.10.17 17:08
Ein freundlices Hallo a, alle,
ich dachte inzwischen wäre mir klar wie die Dinge zu handhaben sind, aber mein Programm stürzt beim Beenden ab.
Zunächst zum Verständnis: Wenn ich zur Laufzeit Objekte erzeuge, muß ich selbst aufräumen (free), wenn es keinen Owner gibt, sonst macht der das. So dachte ich bisher. Oder macht das der Parent? Kann mich da jemand auf die Spur bringen?
Der aktuelle Fall, der mich ins Grübeln bringt:
Ich habe ein TStringGrid um einige Methoden und Properties erweitert. Dazu gehört auch ein Kontextmenu. Im Constructor des Grid wird das Menu erzeugt:
Delphi-Quelltext 1: 2: 3: 4: 5:
| PopupMenu := TPopupMenu.Create ( Self ); PopupMenu.OnPopup := OnPopup ; PopupMenu.AutoPopup := true ; PopupMenu.Items.Create( PopupMenu ) ; for I := 0 to Men - 1 do PopupMenu.Items.Add( TMenuItem.Create( PopupMenu ) ); |
Wird das PopupMenu ausgeklammert, gibt es beim Beenden keinen Fehler, ist es jedoch aktiv, so kommt ein Zugriffsfehler.
Entweder habe ich hier etwas noch nicht richtig verstanden, oder jemand muss das Brett entfernen.
Grüße von der wolkigen Nordsee
Peter Moderiert von Narses: Topic aus Delphi Language (Object-Pascal) / CLX verschoben am Mo 02.10.2017 um 22:36
|
|
Narses
Beiträge: 10181
Erhaltene Danke: 1254
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mo 02.10.17 21:42
Moin!
Peter18 hat folgendes geschrieben : | Wenn ich zur Laufzeit Objekte erzeuge, muß ich selbst aufräumen (free), wenn es keinen Owner gibt, sonst macht der das. |
Der Owner ist der Dateneigentümer und muss eine Instanz einer Formularklasse sein, wenn du möchtest, dass die Objekte beim Beenden des Programmes (oder zumindest beim Freigeben des GUI-Formulares) automatisch mit freigegeben werden sollen. Man kann deinem Code-Schnipsel leider nicht ansehen, ob das Self beim Create die Formularklasse referenziert. Wenn dem so ist, dann sollte das automatische Aufräumen funktionieren.
Peter18 hat folgendes geschrieben : | Oder macht das der Parent? |
Der Parent ist in Controls das Objekt, dass beim Anzeigen der Container ist, das hat also was mit der Darstellung, nicht mit der Dateneigentümerschaft zu tun.
Peter18 hat folgendes geschrieben : | Wird das PopupMenu ausgeklammert, gibt es beim Beenden keinen Fehler, ist es jedoch aktiv, so kommt ein Zugriffsfehler. |
Zumindest mir ist es mit dem Stück Code nicht möglich nachzuvollziehen, warum es zu der Zugriffsverletzung kommt.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 03.10.17 01:59
- Nachträglich durch die Entwickler-Ecke gelöscht -
|
|
jaenicke
Beiträge: 19272
Erhaltene Danke: 1740
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 03.10.17 06:26
Wo kommt denn der Fehler beim Beenden (Stacktrace, ...)?
Sehr komisch mutet mir diese Zeile an:
Delphi-Quelltext 1:
| PopupMenu.Items.Create( PopupMenu ) | Ein Aufruf des Konstruktors einer vorhandenen Instanz von außen ist zu 99,9% nicht korrekt.
In diesem Fall vermute ich ja mal, dass da vorher etwas nicht funktioniert hat. Hast du vielleicht das inherited nicht vorher aufgerufen? Die Zeile muss jedenfalls weg.
Zuletzt bearbeitet von jaenicke am Di 03.10.17 06:27, insgesamt 1-mal bearbeitet
|
|
haentschman
Beiträge: 285
Erhaltene Danke: 33
DX10 Berlin Professional
|
Verfasst: Di 03.10.17 06:27
Moin...
Du machst es dir unendlich schwer. Warum nicht mit dem Objektinspektor?
Beim dynamischen Erzeugen der Objekte, mußt du alle Objekte selbst erzeugen. Die Items bekommen das komplette Menü oder die Form als Owner.
Versuch mal das hier:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| var Item: TMenuItem; ... PopupMenu := TPopupMenu.Create(Self); PopupMenu.OnPopup := OnPopup; PopupMenu.AutoPopup := True; for I := 0 to Men - 1 do begin Item := TMenuItem.Create(Pop); Item.Caption := 'Blubb'; PopupMenu.Items.Add(Item); end; ... lblBla.PopupMenu := PopupMenu |
PS: Über deine Einrückung
Delphi-Quelltext 1: 2:
| PopupMenu := TPopupMenu.Create ( Self ); PopupMenu.OnPopup := OnPopup ; |
...freut sich jeder Code Formatter.
|
|
Peter18
Beiträge: 489
Erhaltene Danke: 2
Delphi4
|
Verfasst: Di 03.10.17 10:24
Hallo Narses, hallo Frühlingsrolle, hallo Sebastian, hallo haentschman,
Dank euch allen!
Narses, Deine Antwort hat endlich das richtige Licht in die Dämmerung gebracht. "Self" war in diesem Fall das Erweiterte Grid. Da das Formular Owner des Grid ist, hat es anscheinend im Grid gelistete Objekte ebenfalls aufgeräumt. Ich habe es zum Testen erst mal in "Application.MainForm" geändert. Für ein Objekt nicht ganz sauber, aber das wird noch geändert.
Du hast Recht, Sebastian, mit entfernen dieser Zeile war auch der Fehler weg.
Haentschman, Dir nochmals besonderen Dank für Deine ausführliche Antwort! So etwas ist immer besonders hilfreich! Den Objektinspektor verwende ich natürlich auch, wenn es Menüs sind, die mit einem Formular zusammen hängen. Hier aber handelt es sich um ein spezielles Menu für das erweiterte Grid und wird deshalb dort erzeugt. Die Formatierung ist entstanden, weil es übersichtlicher ist und ich so Fehler vermeiden kann, die mir anfangs unterlaufen sind. Der Compiler hat manchmal ein vergessenes Semikolon "übersehen", was zu Fehlern führte, die schwer zu finden waren, weil sie sich an ganz anderen Stellen auswirkten.
Grüße von der verregneten Nordsee und einen schönen Feiertag
Peter
|
|
baka0815
Beiträge: 489
Erhaltene Danke: 14
Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
|
Verfasst: Mi 04.10.17 16:20
Genereller Tipp meinerseits: Nach Möglichkeit selbst freigeben.
Wenn man sich auf die Freigabe durch Delphi verlässt, kann man nicht beeinflussen in welcher Reihenfolge die Objekte freigegeben werden. Wenn nun z.B. ein Objekt bei dem anderen registriert ist und sich im Destruktor deregistrieren möchte, das andere Objekt jedoch bereits automatisch freigegeben wurde, kann es zu einer Zugriffsverletzung (gut) oder zum Überschreiben von Speicher (schlecht) kommen.
Daher kann es häufig sinnvoll sein, die Reihenfolge der Freigabe selbst zu bestimmen.
|
|
|