Autor Beitrag
Peter18
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Mo 02.10.17 18: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:

ausblenden 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 user profile iconNarses: Topic aus Delphi Language (Object-Pascal) / CLX verschoben am Mo 02.10.2017 um 22:36
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10181
Erhaltene Danke: 1254

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mo 02.10.17 22:42 
Moin!

user profile iconPeter18 hat folgendes geschrieben Zum zitierten Posting springen:
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.

user profile iconPeter18 hat folgendes geschrieben Zum zitierten Posting springen:
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.

user profile iconPeter18 hat folgendes geschrieben Zum zitierten Posting springen:
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

_________________
There are 10 types of people - those who understand binary and those who don´t.
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 03.10.17 02:59 
- Nachträglich durch die Entwickler-Ecke gelöscht -
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 03.10.17 07:26 
Wo kommt denn der Fehler beim Beenden (Stacktrace, ...)?

Sehr komisch mutet mir diese Zeile an:
ausblenden 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 07:27, insgesamt 1-mal bearbeitet
haentschman
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 285
Erhaltene Danke: 33


DX10 Berlin Professional
BeitragVerfasst: 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:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
var
  Item: TMenuItem; // Zwischenvariablen sind meistens übersichtlicher. :-)
...
PopupMenu := TPopupMenu.Create(Self); // in diesem Falle Owner die Form (wahrscheinlich) 
PopupMenu.OnPopup := OnPopup;      
PopupMenu.AutoPopup := True;
for I := 0 to Men - 1 do
begin
  Item := TMenuItem.Create(Pop); // Owner das gesamte Menü
  Item.Caption := 'Blubb'
  PopupMenu.Items.Add(Item);
end
...
lblBla.PopupMenu := PopupMenu


PS: Über deine Einrückung
ausblenden Delphi-Quelltext
1:
2:
PopupMenu           := TPopupMenu.Create ( Self );
PopupMenu.OnPopup   := OnPopup                   ;

...freut sich jeder Code Formatter. :zwinker:
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 489
Erhaltene Danke: 14

Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
BeitragVerfasst: 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.