Entwickler-Ecke
Grafische Benutzeroberflächen (VCL & FireMonkey) - Owner, Parent, Destructor: noch etwas unklar
Peter18 - Mo 02.10.17 18:08
Titel: Owner, Parent, Destructor: noch etwas unklar
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 - Mo 02.10.17 22: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. :nixweiss:
cu
Narses
Delete - Di 03.10.17 02:59
- Nachträglich durch die Entwickler-Ecke gelöscht -
jaenicke - Di 03.10.17 07: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.
haentschman - Di 03.10.17 07:27
Moin... 8)
Du machst es dir unendlich schwer. :zwinker: 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. :zwinker:
Peter18 - Di 03.10.17 11: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 - Mi 04.10.17 17: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.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!