![]() |
Self nicht definiert nach dem Create?
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 |
AW: Self nicht definiert nach dem Create?
Hi,
The reason is first time it fail because Self is nil (not defined), and that because of this global var
Code:
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...
var MeinForm: TMeinForm;
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. .. |
AW: Self nicht definiert nach dem Create?
"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:
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:
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;
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; |
AW: Self nicht definiert nach dem Create?
Zitat:
Dazu noch wie bereits vorgeschlagen nur eine lokale Variable für das Formular und kein with, dann kann schon nicht mehr viel schiefgehen. Zitat:
Im Grunde kann man Stellen mit with nicht sinnvoll debuggen. |
AW: Self nicht definiert nach dem Create?
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 |
AW: Self nicht definiert nach dem Create?
Tipp:
Ändere die Funktion mal ab auf
Delphi-Quellcode:
bzw. unten auf
class function Execute() : Boolean;
Delphi-Quellcode:
.
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 |
AW: Self nicht definiert nach dem Create?
Zitat:
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; |
AW: Self nicht definiert nach dem Create?
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. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:16 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