AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Self nicht definiert nach dem Create?
Thema durchsuchen
Ansicht
Themen-Optionen

Self nicht definiert nach dem Create?

Ein Thema von looseleaf · begonnen am 2. Feb 2024 · letzter Beitrag vom 2. Feb 2024
Antwort Antwort
looseleaf

Registriert seit: 25. Mai 2011
58 Beiträge
 
#1

Self nicht definiert nach dem Create?

  Alt 2. Feb 2024, 10:12
Liebe Gemeinde,

wir verwenden in unserem Programm immer wieder quasi-statische Execute() Methoden, um Froms zu ersellen und am Ende wieder freizugeben. Nach diesem Muster:

var MeinForm: TMeinForm;

function TMeinForm.Execute(): Boolean;
begin
Result := false;
MeinForm := TMeinForm.Create(Application);
With MeinForm do
try
// tuwas
Result := ShowModal=mrOk;
finally
Free;
end
end;


Wenn wir hier beim // tuwas auf Self referenzieren, ist das eine blöde Idee, oder? Ich glaube auch zu verstehen warum: Execute() ist hier noch keine Methode des Objekes, daher ergibt Self keinen Sinn. Was ich aber nich verstehe: Bei einem zweiten Aufruf funkioniert der Zugriff auf Self, obwohl am Ende ein Free steht. Kann mir wer auf die Sprünge helfen, warum das beim zweiten Mal geht? Und das Self zeigt lt. Debugger auch ab der Zeile mit dem .Create() auf dieselbe Adresse wie MeinForm.

Wir verwenden hier die MeinForm, dann funktioniert's wie erwartet.

Fragt bitte nicht, warum hier eine Variable verwendet wird, das ist Code von vor über 20 Jahren.

Danke
Stefan
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
213 Beiträge
 
#2

AW: Self nicht definiert nach dem Create?

  Alt 2. Feb 2024, 10:41
Hi,

The reason is first time it fail because Self is nil (not defined), and that because of this global var
Code:
var MeinForm: TMeinForm;
Initially it is nil (zeroed), after creating it once, it will held a valid value and full MienForm structure/object, BUT after freeing it, Delphi Memory Manager (FastMM) most likely will save time and not clear the allocated memory hence the structure of the TMainForm is reserved and pointing to a valid VMT, also you are free the global without nil (zeroing) hence it still point to a valid to read but not valid to be trusted pointer to memory/data/object/class/structure...

If you enable Memory Debugging tools then it will point that this is case of use after free, i mean the second call.
Also you can simply nil that var and get failure on the second time, a consistent failure as it should be.

Also this is hidden and dangerous bug as accessing Self second time could lead to undefined behavior as the memory from MM point of view is freed and empty and can be reused, this can lead to all sort of unexplained exception and no sense stack traces....

The simplest way to see this exception and protect against it is
1) Don't use global var !
2) In this case im my opinion is a legitimate place to use FreeAndNil(MeinForm); instead of MeinForm.Free;
3) Before calling MeinForm := TMeinForm.Create(Application); you really should check for Assigned(MeinForm) then raise an exception, that Create should only happen if MeinForm already created to prevent memory corruption.
..
  Mit Zitat antworten Zitat
BigAl

Registriert seit: 6. Sep 2008
Ort: Kehl
495 Beiträge
 
Delphi 12 Athens
 
#3

AW: Self nicht definiert nach dem Create?

  Alt 2. Feb 2024, 10:41
"Self" geht bei statischen Methoden nicht. Das ist ja quasi eine globale Funktion. Anstelle "Self" würde ich immer "MeinForm" verwenden.

Grundsätzlich würde ich - wenn es schon so gemacht sein soll - das "MeineForm" als lokale Variable der Funktion definieren:

Delphi-Quellcode:
function TMeinForm.Execute(): Boolean;
var
  MeinForm: TMeinForm;
begin
  Result := false;
  MeinForm := TMeinForm.Create(Application);
  With MeinForm do
  try
    // tuwas
    Result := ShowModal = mrOk;
  finally
    Free;
  end
end;
Auf "with" würde ich ganz verzichten. Das "with" habe ich vor 20 Jahren oder aus meinem Repertoir gestrichen. Das macht den Code schwer zu lesen und teilweise zu debuggen:

Delphi-Quellcode:
function TMeinForm.Execute(): Boolean;
var
  MeinForm: TMeinForm;
begin
  Result := false;
  MeinForm := TMeinForm.Create(Application);
  try
    // tuwas
    Result := MeinForm.ShowModal = mrOk;
  finally
    MeinForm.Free;
  end
end;
Man sollte nie so viel zu tun haben, dass man zum Nachdenken keine Zeit mehr hat. (G.C. Lichtenberg)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.350 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Self nicht definiert nach dem Create?

  Alt 2. Feb 2024, 12:21
wir verwenden in unserem Programm immer wieder quasi-statische Execute() Methoden, um Froms zu ersellen und am Ende wieder freizugeben.
Wie wäre es, daraus echte statische Methoden zu machen? Also class function statt function? Dann kannst du Self gar nicht fälschlicherweise verwenden.

Dazu noch wie bereits vorgeschlagen nur eine lokale Variable für das Formular und kein with, dann kann schon nicht mehr viel schiefgehen.

Und das Self zeigt lt. Debugger auch ab der Zeile mit dem .Create() auf dieselbe Adresse wie MeinForm.
Der Debugger kann mit with nichts anfangen. Insofern musst du in der Konstellation sehr vorsichtig sein, wenn du mit dem Debugger arbeitest. Das with wird dort einfach ignoriert, weshalb da sehr wilde Daten herauskommen können.

Im Grunde kann man Stellen mit with nicht sinnvoll debuggen.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!

Geändert von jaenicke ( 2. Feb 2024 um 12:24 Uhr)
  Mit Zitat antworten Zitat
looseleaf

Registriert seit: 25. Mai 2011
58 Beiträge
 
#5

AW: Self nicht definiert nach dem Create?

  Alt 2. Feb 2024, 14:11
Danke für eure Antworten, mir ist ehrlicherweise nicht ganz klar, warum das überhaupt zulässig ist, aber wird wohl daran liegen, dass die Methode nicht als class function definiert ist.

Mein Chef hat diese Art des Codens irgendwann Ende der 90er in einem Forum gefunden und übernommen - funktioniert ja auch. Meistens

Ich würde hier ohnehin für ein sauberes Singleton plädieren mit einer getMeinForm() und ohne globaler Variable...

Wir werden unseren Code durchforsten, ob wir noch bei anderen Formularen so einen Schmonzes stehen haben

Schönes Wochenende,
Stefan
  Mit Zitat antworten Zitat
Incocnito

Registriert seit: 28. Nov 2016
210 Beiträge
 
#6

AW: Self nicht definiert nach dem Create?

  Alt 2. Feb 2024, 15:58
Tipp:
Ändere die Funktion mal ab auf class function Execute() : Boolean; bzw. unten auf class function TMeinForm.Execute() : Boolean; .
class function / class procedure wäre für deinen Anwendungsfall logischer,
da du vom Objekt keine Instanz brauchst.
Dort müsste er auch meckern "was ist Self?".

Liebe Grüße aus dem Norden
Incocnito
  Mit Zitat antworten Zitat
Andreas L.

Registriert seit: 23. Mai 2011
Ort: Furth im Wald
308 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: Self nicht definiert nach dem Create?

  Alt 2. Feb 2024, 16:34
Tipp:
Ändere die Funktion mal ab auf class function Execute() : Boolean; bzw. unten auf class function TMeinForm.Execute() : Boolean; .
class function / class procedure wäre für deinen Anwendungsfall logischer,
da du vom Objekt keine Instanz brauchst.
Dort müsste er auch meckern "was ist Self?".

Liebe Grüße aus dem Norden
Incocnito
So ähnlich halte ich es auch immer:
Delphi-Quellcode:
type
  TMyForm = class(TForm)
    //...
  public
    class function Execute: Boolean;
  end;

class function TMyForm.Execute: Boolean;
var
  FormDlg: TMyForm;
begin
  FormDlg := TMyForm.Create(Application);
  try
    // ggf. irgendwas vor dem Öffnen des Dialogs machen
    FormDlg.LoadOptions;

    // Dialog öffnen
    Result := FormDlg.ShowModal = mrOK;

    // ggf. nach dem Schließen des Forms irgendwas speichern
    if Result then
      FormDlg.SaveOptions;
  finally
    FreeAndNil(FormDlg);
  end;
end;
Andreas Lauß
Blog
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.152 Beiträge
 
Delphi 12 Athens
 
#8

AW: Self nicht definiert nach dem Create?

  Alt 2. Feb 2024, 16:36
Nein, Class-Function kennt auch ein Self, nur ist es dort keine Instanz (TObject), sondern ein Typ (TClass).

Eine Static-Class-Function kennt kein Self.


Aber alles egal, da Self nur ein unsichtbarer Parameter an Klassenmethoden ist
und in einem WITH sowieso nicht existiert.


Abgesehn davon, dass man WITH nach Möglichkeit eh nicht benutzen sollte.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:03 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz