![]() |
Delphi-Version: 5
Pointer auf Instanz zurückgeben
Moin.
Ich stell mich gerade zu blöd an, finde aber den Fehler nicht: Ich versuche gerade, mir von einer Prozedur einen Zeiger auf ein in der Prozedur erzeugtes Objekt zurückgeben zu lassen. Offenbar zeigt der Zeiger unmittelbar nach Rückkehr auf das Objekt mit dem richtigen Inhalt (1234). Sobald dann ein neues Objekt (egal was) erzeugt wird, wird offenbar mein in der Prozedur erzeugtes Objekt überschrieben. Die Freigabe des Objekts endet sogar in einer Schutzverletzung, offenbar wurde das Ding schon freigegeben. Aber durch wen und wieso? Hat jemand eine Idee? PS: Als erste Zeile steht "Delphi-Version: 5". Hab ich nicht geschrieben, steht auch nicht in meinem Profil, glaube ich... Keine Ahnung wie das dahin kommt.
Delphi-Quellcode:
unit Unit1;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; type TMyClass = class public Wert: integer; end; PMyClass = ^TMyClass; TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} procedure Test(var Zeiger: PMyClass); var MyObject: TMyClass; begin MyObject := TMyClass.Create; MyObject.Wert := 1234; Zeiger := @MyObject; end; procedure TForm1.Button1Click(Sender: TObject); var pObjekt: PMyClass; AnderesObjekt: TMyClass; begin Test(pObjekt); Caption := pObjekt^.Wert.ToString; // OK, 1234 AnderesObjekt := TMyClass.Create; AnderesObjekt.Wert := 9876; Caption := pObjekt^.Wert.ToString; // Nun nicht mehr 1234... AnderesObjekt.Free; pObjekt^.Free; // AV end; end. |
AW: Pointer auf Instanz zurückgeben
MyObject: TMyClass ist schon die Referenz auf die Instanz.
Wieso noch eine Zeiger auf den Zeiger nutzen? |
AW: Pointer auf Instanz zurückgeben
Weil ich in einer Anwendung eine Methode ersetzen will, die bereits existent ist und an vielen Stellen verwendet wird. Das Ding selbst ist in Assembler geschrieben und gibt mir einen Pointer auf ein Objekt zurück.
Das muss doch auch in Pascal irgendwie gehen? Und wieso verschwindet das Objekt, obwohl niemand es freigibt? |
AW: Pointer auf Instanz zurückgeben
Zitat:
Delphi-Quellcode:
Das kann so nicht funktionieren
procedure Test(var Zeiger: PMyClass);
var MyObject: TMyClass; begin MyObject := TMyClass.Create; MyObject.Wert := 1234; Zeiger := @MyObject; // Das zeigt jetzt auf die lokale Variable auf dem Stack end; |
AW: Pointer auf Instanz zurückgeben
Naja, das ist doch ein Objekt und keine einfache lokale Integer-Variable oder so...
Und ein Objekt, das nicht freigegeben wird, sollte doch für immer und ewig im Speicher liegen? Ich dachte immer, bei Delphi wird nichts automatisch aufgeräumt? |
AW: Pointer auf Instanz zurückgeben
mit der Zuweisung
Delphi-Quellcode:
Zeiger := @MyObject;
wird Zeiger die Adresse von der Variablen MyObject zugewiesen damit hast Du einen Zeiger auf einen Zeiger und in dem Fall auf die lokale variable Noch mal: Das geht nicht |
AW: Pointer auf Instanz zurückgeben
Instanz-Variablen sind bereits Referenzen. So wird es funktionieren:
Delphi-Quellcode:
procedure Test(var aObject: TMyClass);
begin aObject := TMyClass.Create; aObject.Wert := 1234; end; procedure TForm1.Button1Click(Sender: TObject); var MyObject: TMyClass; AnderesObjekt: TMyClass; begin Test(MyObject); Caption := MyObject.Wert.ToString; // OK, 1234 AnderesObjekt := TMyClass.Create; AnderesObjekt.Wert := 9876; Caption := MyObject.Wert.ToString; // Nun immer noch 1234... AnderesObjekt.Free; MyObject.Free; // keine AV end; |
AW: Pointer auf Instanz zurückgeben
Danke euch beiden!
Ah ja, ok: Mein pObjekt-Zeiger zeigt auf den lokalen Zeiger im Stack, der wiederum auf das Objekt im Heap zeigt. Nach Verlassen der Prozedur Test() wird der lokale Zeiger abgeräumt (das war mir vorher nicht wirklich klar), mein pObjekt-Zeiger wird in Zukunft auf die nächste Variable, die auf dem Stack erzeugt wird, zeigen, und auf das eigentliche Objekt im Heap zeigt gar nichts mehr. Gibt Sinn. Ich hatte übrigens bisher leider überlesen (*schluck*), das die erwähnte Assembler-Methode gar kein mit Txyz=class ... end; sondern ein mit Txyz=object ... end; erzeugtes Objekt zurückliefert. Und das ist dann offenbar direkt das Objekt, kein Objekt+Zeiger darauf. Wieder was gelernt... So funktioniert es übrigens:
Delphi-Quellcode:
unit Unit1;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; type TMyClass = object public Wert: integer; procedure Free; end; PMyClass = ^TMyClass; TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} procedure Test(var Zeiger: PMyClass); begin New(Zeiger); Zeiger^.Wert := 1234; end; procedure TForm1.Button1Click(Sender: TObject); var pObjekt: PMyClass; AnderesObjekt: TMyClass; EineBitmap: TBitmap; begin Test(pObjekt); Caption := pObjekt^.Wert.ToString; // OK, 1234 // AnderesObjekt := TMyClass.Create; // AnderesObjekt.Wert := 9876; // Das geht so eh nicht, daher irgendein anderes Objekt zum Testen: EineBitmap := TBitmap.Create; Caption := pObjekt^.Wert.ToString; // Yeah, 1234... // AnderesObjekt.Free; EineBitmap.Free; pObjekt^.Free; end; { TMyClass } procedure TMyClass.Free; begin Dispose(@Self); end; end. |
AW: Pointer auf Instanz zurückgeben
Zitat:
|
AW: Pointer auf Instanz zurückgeben
Wie schon gesagt wurde, ein "Objekt" ist bereits ein Pointer, könnte also einfach direkt gekastet werden.
Du speicherst dir aber keinen Zeiger auf das Objekt, sondern auf die Variable, in welcher der Objektzeiger gepsiechert ist. Außerden ist diese Variable auch noch eine lokale Variale auf dem Stack, wobei diese Variable also beim Verlassen der Methode zerstört/ungültig wird. Auf was dein Zeiger nun zeigt, ist anschließend also "irgenwas", aber nicht mehr diese Variable mit dem Zeiger. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:28 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 by Thomas Breitkreuz