Autor Beitrag
Mortal-Shadow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 110



BeitragVerfasst: Do 28.05.09 12:14 
Hi,

ich wollte wissen was passiert, wenn ich ein Object sich selbst zerstören lasse.
Irgendwie hätte ich einen Fehler erwartet, aber folgendes funktioniert ganz gut:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
unit Unit2;

interface
type
  TTestingclass = class
    procedure Suicide;
  private
    x : integer;
  end;

implementation
uses
unit1;


Procedure Testingclass.Suicide;
begin
self.Destroy;
Inc(x);
end;

end.


Funktioniert das, weil der Code abgebrochen wird nach self.destroy, oder ist dass Zufall und ich sollte so etwas vermeiden.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Do 28.05.09 12:42 
Das ist Zufall, weil der Speicher noch nicht wieder vergeben ist. Sowas bitte unterlassen. Das ist eine Quelle für SEHR SCHWER ZU FINDENDE Fehler (ich kenn jemand, der hat wegen sowas nen Fehler gehabt, der erst nach etwa 4 Wochen nach Programmstart auftauchte ...)

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Mortal-Shadow Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 110



BeitragVerfasst: Do 28.05.09 12:57 
Ah gut, vielen Dank.
Habe befürchtet, dass das schiefgehen kann, war mir aber nicht sicher.
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Do 28.05.09 13:31 
Es ist kein guter Stil, später schwer zu verstehen und nicht zu empfehlen, trotzdem erkläre ich wann du das theoretisch darfst, denn sowas wird teilweise auch im VCL-Code praktiziert.

Du darfst nach dem Destroy noch so viel Code ausführen wie du willst, solange nicht auf Speicher des Objekts (z.B. auf Felder) zugegriffen wird. Du darfst also auf keine privaten Variablen oder sonstiges zugreifen sondern darfst nur noch das, was eine Class-Methode auch dürfte.

Du musst demnach auch sicherstellen, dass deine Methode, die das Objekt zerstört, nicht von einer anderen Methode aufgerufen wurde, die später noch auf das Objekt zugreift.

Die VCL löst das so, in dem sie sich selbst eine Windows-Message postet. Der Handler dieser Message zerstört dann das Objekt.
Da Windows-Messages auf Ebene von TApplication.HandleMessage (oder analog) ausgelöst wird, ist die oben beschriebene verbotene Schachtelung in den meisten Fällen ausgeschlossen.

Es sei denn, du schmückst deinen Code mit Application.ProcessMessages (was man aber meiner Meinung nach sowieso nie tun sollte). Denn dann wird die Destroy-Message nicht mehr auf Ebene von TApplication.ProcessMessage ausgeführt sondern dort wo Application.ProcessMessages steht, d.h. evtl. in irgend einer Methode und wir sind wieder beim gleichen Schachtelungsproblem. Tatsächlich ist es möglich, auf diese Art eine Access Violation in der VCL zu erzeugen.

Was weniger problematisch ist, wenn du deine Methode klar als eine Alternative zu Free erkenntlich machst und diese nur "von aussen" ausführst, genau wie Free selbst. Natürlich gilt auch hier, dass du nach dem Zerstören nicht mehr auf Objektfelder zugreifst.

Fazit: Es ist möglich, aber nur wenn du ganz genau weisst, was du tust und gewisse Fälle ausschliessen kannst. Das dürfte dir vermutlich nur gelingen, wenn du deinen gesamten Code wirklich unter Kontrolle hast.