Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Zugriffsverletzung bei free? (https://www.delphipraxis.net/87694-zugriffsverletzung-bei-free.html)

Hyperspacer 4. Mär 2007 19:07


Zugriffsverletzung bei free?
 
Ich beiß gleich in die tischkante.. :wall:

Ich erstelle dynamisch ein Tedit, dem ich zwei ereignisproceduren zuweise:
Delphi-Quellcode:
with TEdit.Create(form1) do
  begin
    Parent := Form1;
    Top := 50;
    Left := 100;

    SetFocus;

    OnExit := ItemEditOnExit;
    OnKeyDown := ItemEditOnKeyDown;
  end;
So weit so gut. Hier nun die Proceduren:
Delphi-Quellcode:
procedure TForm1.ItemEditOnExit(Sender: TObject);
begin
  ListView1.ItemFocused.SubItems.Strings[0] := (Sender as TEdit).Text;
  Sender.Free;
end;

procedure Tform1.ItemEditOnKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  If Key = VK_Return then
    begin
      ListView1.ItemFocused.SubItems.Strings[0] := (Sender as TEdit).Text;
      Sender.Free;
    end;
end;
Wenn die OnExit Procedure ausgeführt wird, geht alles glatt. Aber wenn die OnKeyDown Procedure ausgeführt wird gibt es eine wunderschöne Zugriffsverletzung nachdem Free.
Ich habe schon versucht das Edit nicht in der OnKeyDown Procedure zu freen, sondern von dort die OnExit Procedure auszuführen, was allerdings zum selben Fehler führte.

Wer kann mir sagen wie ich diesen Fehler beheben oder umschippern kann?

mfg
Daniel

Neutral General 4. Mär 2007 19:21

Re: Zugriffsverletzung bei free?
 
Delphi-Quellcode:
procedure Tform1.ItemEditOnKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  If Key = VK_Return then
    begin
      ListView1.ItemFocused.SubItems.Strings[0] := (Sender as TEdit).Text;
      TEdit(Sender).OnExit := nil; // <---
      Sender.Free;
    end;
end;
Schreib das mal so.. Is nur son Gefühl...
Keine Garantie!

Gruß
Neutral General

SirThornberry 4. Mär 2007 19:29

Re: Zugriffsverletzung bei free?
 
innerhalb eines Events sollte man NIE die Komponente frei geben denn das Event ist etwa so aufgebaut
Delphi-Quellcode:
//Wenn OnChange zugewiesen ist
if Assigned(OnChange) then
  OnChange(Self); //OnChange aufrufen
Self.DoAnything; //Wenn jetzt die Componente im OnChange freigegeben wurde knallts weil Self ja nicht mehr auf was gültiges zeigt sondern frei gegeben wurde

Hyperspacer 4. Mär 2007 19:41

Re: Zugriffsverletzung bei free?
 
Danke für die schnellen Antworten!

@SirThornberry:
Klingt logisch aber da gibt es nochetwas.
Ich erstelle das Edit zum ersten mal. Dann schreibe ich irgendetwas hinein und drücke "Enter". Peng Fehler. Das Edit ist nach dem Fehler wenigstens nicht mehr zu sehen, ob es auch wirklich weg ist kann ich nichtsagen. Der Text wurde erfolgreich in die Liste geschrieben. Wenn ich jetzt erneut ein Edit erstelle, etwas hineinschreibe und "enter" drücke gibt es KEINEN fehler!
Jetzt bin ich völlig verwirrt. :coder2:

Edit: Überigens herzlichen Glückwunsch zum 6.666sten Beitrag :thumb:

TonyR 4. Mär 2007 20:39

Re: Zugriffsverletzung bei free?
 
Ich weis ja nicht, was du vor hast, aber wäre es nicht auch eine Idee, das Edit im Designer oder von mir aus im Oncreate zu erstellen und es erst beim schließen des Progs wieder Freizugeben???
Um es zwischenzeitlich unsichtbar zu machen, kann man ja Hide benutzen :gruebel:

Hyperspacer 4. Mär 2007 20:51

Re: Zugriffsverletzung bei free?
 
Manchmal sind die Antworten so einfach! :mrgreen:
Nur der Vollständigkeit halber: Ich habe ein Listview und will auch die subitems direkt editieren können. dafür hatte ich vor (was auch soweit funktioniert) bei einem doppelklick auf einen bestimmten eintrag im listview ein editfeld an dieser stelle zu erstellen mit dem man dann den eintrag bearbeiten kann.
Aber man kann ja auf einfach eins von anfang an erstellen, unsichtbar machen und dann immer an die richtige stelle verschieben und sihtbar machen...

okay danke an euch alle!
... Obowhl ich den fehler schon komisch finde

mfg
Daniel

SirTwist 4. Mär 2007 22:15

Re: Zugriffsverletzung bei free?
 
Zitat:

Zitat von Hyperspacer
... Obowhl ich den fehler schon komisch finde

Mit diesem Code hier:
Delphi-Quellcode:
with TEdit.Create(form1) do begin
  ...
end;
legst Du zwar ein TEdit an und initialisierst du es, aber direkt nach dem End wird es wieder freigegeben, weil du es keiner Variablen zuweist. Und damit arbeiten all deine Routinen, die du zuweist, im luftleeren Raum, und dein Sender.Free gibt bereits freien Speicher nochmal frei.

Wenn Du schon Controls on-the-fly erzeugen willst, musst Du sie in einer Variable speichern, und zwar keiner lokalen innerhalb der Prozedur, sondern innerhalb der aktuellen Klasse/des aktuellen Forms:

Delphi-Quellcode:
  tmp_edit := TEdit.Create(form1);
  with tmp_edit do begin
    tmp_edit.Parent := form1;
  end;
und dann spätestens im FormClose-Event:
Delphi-Quellcode:
  FreeAndNil(tmp_edit);

Christian Seehase 4. Mär 2007 22:21

Re: Zugriffsverletzung bei free?
 
Moin Daniel,

nur um das

Zitat:

Zitat von Hyperspacer
Wenn ich jetzt erneut ein Edit erstelle, etwas hineinschreibe und "enter" drücke gibt es KEINEN fehler!

mal zu klären.

Wenn Du das Free ausführst, wird der Speicher, den die Komponente belegt hat, zur erneuten Verwendung freigegeben.
Je nach Konstellation kann es dabei auch vorkommen, das die Komponente dennoch so vollständig erhalten bleibt, das spätere Zugriffe darauf noch einwandfrei funktionieren, es kann aber auch sein, dass entscheidende Bereiche schon wieder überschrieben wurden => AV.

Du kannst das vergleichen mit dem Löschen einer Datei.
Wenn danach noch nicht viel auf der Platte geändert wurde, stehen die Chancen recht gut diese wiederherstellen zu können, es können aber auch schon Bereiche davon überschrieben worden sein.

xaromz 4. Mär 2007 22:25

Re: Zugriffsverletzung bei free?
 
Hallo,

nur um das geradezurücken:
Zitat:

Zitat von SirTwist
Mit diesem Code hier:
Delphi-Quellcode:
with TEdit.Create(form1) do begin
  ...
end;
legst Du zwar ein TEdit an und initialisierst du es, aber direkt nach dem End wird es wieder freigegeben, weil du es keiner Variablen zuweist. Und damit arbeiten all deine Routinen, die du zuweist, im luftleeren Raum, und dein Sender.Free gibt bereits freien Speicher nochmal frei.

Diese Aussage ist natürlich Blödsinn. Das Objekt wird nicht freigegeben (Delphi-Klassen besitzen keine Referenzzählung und Delphi hat auch keinen GC). Es existiert nur keine Variable, mit der das Objekt angesprochen werden kann.

Gruß
xaromz

TStringlist 4. Mär 2007 23:57

Re: Zugriffsverletzung bei free?
 
edit: stand schon irgendwo

IngoD7 5. Mär 2007 07:29

Re: Zugriffsverletzung bei free?
 
Zitat:

Zitat von xaromz
nur um das geradezurücken:
Zitat:

Zitat von SirTwist
Mit diesem Code hier:
Delphi-Quellcode:
with TEdit.Create(form1) do begin
  ...
end;
legst Du zwar ein TEdit an und initialisierst du es, aber direkt nach dem End wird es wieder freigegeben, weil du es keiner Variablen zuweist. [...]

Diese Aussage ist natürlich Blödsinn. Das Objekt wird nicht freigegeben (Delphi-Klassen besitzen keine Referenzzählung und Delphi hat auch keinen GC). Es existiert nur keine Variable, mit der das Objekt angesprochen werden kann.

Ich setze noch einen drauf.

Zitat:

Zitat von SirTwist
Wenn Du schon Controls on-the-fly erzeugen willst, musst Du sie in einer Variable speichern, und zwar keiner lokalen innerhalb der Prozedur, sondern innerhalb der aktuellen Klasse/des aktuellen Forms:
Delphi-Quellcode:
  tmp_edit := TEdit.Create(form1);
  with tmp_edit do begin
    tmp_edit.Parent := form1;
  end;

Nur der Vollständigkeit halber: Müssen muss er das nicht. :wink:

Da bei ihm Form1 der Owner vom Edit ist, ist das Edit über die Liste Form1.Components referenzierbar. Und weil Form1 der Parent vom Edit ist, ist das Edit ebenfalls in Form1.Controls greifbar. Dazu sollte allerdings sinnigerweise Edit.Name beim Createn belegt werden.


Zitat:

Zitat von SirTwist
und dann spätestens im FormClose-Event:
Delphi-Quellcode:
  FreeAndNil(tmp_edit);

Auch nein. Weil das Form1 hier der Owner vom Edit ist, würde das Edit automatisch beim Freigeben der Form1 auch freigegeben werden.
Objekte vom Typ TComponent (bzw. dessen Ableitungen) zerstören die Komponenten, deren Owner sie sind, bei ihrer eigene Freigabe immer mit.

SirTwist 5. Mär 2007 10:35

Re: Zugriffsverletzung bei free?
 
Jepp, Ihr habt natürlich recht :-)

Daran, dass das Control durch die Zuweisung des Parents in die Control-Liste des Parents aufgenommen wird, habe ich wirklich nciht gedacht.

Und dass ein Objekt einfach so im Raum stehen bleibt, auch ohne jede Referenzierung... nun, ich bin bislang immer vom Gegenteil ausgegangen, habe das gerade mal überprüft und Du hast natürlich recht. Das habe ich wohl von Perl falsch übernommen.

Hyperspacer 7. Mär 2007 19:16

Re: Zugriffsverletzung bei free?
 
Okay also das problem an sich hab ich jetzt mit einem unsichtbaren edit umgangen, das ich verschiebe und sichtbar mache wenn ich es benötige.
Aber der Grund des Fehlers ist mir immer noch nicht so ganz klar. Schließlich gibts es ihn ja nur bei einem der beiden Events...
Also kann doch das hier in diesem fall nicht zutreffen: (oder???)

[by SirThornberry]
Zitat:

//Wenn OnChange zugewiesen ist
if Assigned(OnChange) then
OnChange(Self); //OnChange aufrufen
Self.DoAnything; //Wenn jetzt die Componente im OnChange freigegeben wurde knallts weil Self ja nicht mehr auf was gültiges zeigt sondern frei gegeben wurde
Und hierbei

[by Christian Seehase]
Zitat:

Wenn Du das Free ausführst, wird der Speicher, den die Komponente belegt hat, zur erneuten Verwendung freigegeben.
Je nach Konstellation kann es dabei auch vorkommen, das die Komponente dennoch so vollständig erhalten bleibt, das spätere Zugriffe darauf noch einwandfrei funktionieren, es kann aber auch sein, dass entscheidende Bereiche schon wieder überschrieben wurden => AV.
müsste dann bei einem erfolgreichen Freigeben auch das Edit von der Bildfäche verschwinden.. Aber das tut es ja nicht...Es bleibt funktionsfähig da... :wiejetzt:

Christian Seehase 7. Mär 2007 21:19

Re: Zugriffsverletzung bei free?
 
Moin Hyperspacer,

Zitat:

Zitat von Hyperspacer
müsste dann bei einem erfolgreichen Freigeben auch das Edit von der Bildfäche verschwinden.. Aber das tut es ja nicht...Es bleibt funktionsfähig da...

Du hast geschrieben, dass es beim ersten mal eine AV gibt, beim zweitem mal nicht.
Davon, dass das Edit danach immer noch funktionsfähig ist war bislang nicht die Rede.

So unmittelbar erklären, könnte ich das nicht.
Wenn Du mir mal den kompletten Code mit dem sich das reproduzieren lässt zur Verfügung stellen kannst, könnte ich mal versuchen dem mit Hilfe der Debug-DCUs auf den Grund zu gehen. Die dürften bei Deiner Personal nicht dabei sein.

IngoD7 8. Mär 2007 18:35

Re: Zugriffsverletzung bei free?
 
Die sichtbaren Auswirkungen könnten "Zufall" sein!
Ich habe das Beispiel aus dem ersten Posting hier nachvollzogen. Das Edit wird bei mir mit einem Button-Click erzeugt.
Ich bekomme immer eine Exception, egal beim wievielten erzeugenten Edit ich Enter drücke. Das Edit bleibt bei mir nie sichtbar, das Programm schmiert immer ab.

Vermutung:
Die OnExit Methode funktioniert nur ohne Fehler, weil sie in der ganzen Kette der OnExit-Ereignisbehandlung als letztes abgearbeitet wird und nicht zum Edit zurückkehren muss. Ich habe das jetzt nicht step-for-step nachvollzogen, aber ganz viel anders kann es (zumindest sinngemäß) nicht sein.

Die OnKeyDown-Methode muss aber zum Edit zurückkehren, das es aber nach dem Free nicht mehr gibt --> Folge: Crash.

Eigentlich ist es aber auch wurscht, wieso und weshalb ...

Es ist und bleibt der alte Grundsatz: Objekte nie in einer eigenen Ereignisbehandlungsmethode freigeben!

Grundsatz beachten und glücklich sein. :cyclops:

((Irgendwo steht hier oder im DF aber auch eine Umgehung, mit der man eine "Quasi-Selbstzerstörung" vornehmen kann.))

Hyperspacer 8. Mär 2007 19:53

Re: Zugriffsverletzung bei free?
 
Nabend,

Zitat:

Zitat von Christian Seehase
Wenn Du mir mal den kompletten Code mit dem sich das reproduzieren lässt zur Verfügung stellen kannst, könnte ich mal versuchen dem mit Hilfe der Debug-DCUs auf den Grund zu gehen.

Danke für deine Unterstüzung :thumb: , aber so extrem wichtig ist es ja nicht --> Hab das Problem ja nun umgangen.

Zitat:

Zitat von IngoD7
Es ist und bleibt der alte Grundsatz: Objekte nie in einer eigenen Ereignisbehandlungsmethode freigeben!

Grundsatz beachten und glücklich sein. Cyclops

Ich werds ab nun beachten..und glücklich sein :dancer: :coder:

Nochmal danke an alle, die sich mit dem Problem befasst haben. :cheers:

mfg Daniel


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:21 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