AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Pointer auf Instanz zurückgeben

Ein Thema von idontknow · begonnen am 8. Mai 2022 · letzter Beitrag vom 9. Mai 2022
Antwort Antwort
Seite 1 von 2  1 2      
idontknow

Registriert seit: 21. Apr 2008
Ort: Schleswig-Holstein
60 Beiträge
 
Delphi 11 Alexandria
 
#1

Pointer auf Instanz zurückgeben

  Alt 8. Mai 2022, 17:46
Delphi-Version: 5
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.
Oliver
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.202 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Pointer auf Instanz zurückgeben

  Alt 8. Mai 2022, 18:12
MyObject: TMyClass ist schon die Referenz auf die Instanz.
Wieso noch eine Zeiger auf den Zeiger nutzen?
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
idontknow

Registriert seit: 21. Apr 2008
Ort: Schleswig-Holstein
60 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Pointer auf Instanz zurückgeben

  Alt 8. Mai 2022, 18:57
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?
Oliver
  Mit Zitat antworten Zitat
Fritzew

Registriert seit: 18. Nov 2015
Ort: Kehl
678 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Pointer auf Instanz zurückgeben

  Alt 8. Mai 2022, 19:09
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?
Weil in der procedure die Adresse der lokalen Variablen zurückgegeben wird

Delphi-Quellcode:
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;
Das kann so nicht funktionieren
Fritz Westermann
  Mit Zitat antworten Zitat
idontknow

Registriert seit: 21. Apr 2008
Ort: Schleswig-Holstein
60 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Pointer auf Instanz zurückgeben

  Alt 8. Mai 2022, 19:44
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?
Oliver
  Mit Zitat antworten Zitat
Fritzew

Registriert seit: 18. Nov 2015
Ort: Kehl
678 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Pointer auf Instanz zurückgeben

  Alt 8. Mai 2022, 20:24
mit der Zuweisung
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
Fritz Westermann
  Mit Zitat antworten Zitat
samso

Registriert seit: 29. Mär 2009
439 Beiträge
 
#7

AW: Pointer auf Instanz zurückgeben

  Alt 9. Mai 2022, 06:58
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;
  Mit Zitat antworten Zitat
idontknow

Registriert seit: 21. Apr 2008
Ort: Schleswig-Holstein
60 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Pointer auf Instanz zurückgeben

  Alt 9. Mai 2022, 08:32
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.
Oliver
  Mit Zitat antworten Zitat
peterbelow

Registriert seit: 12. Jan 2019
Ort: Hessen
704 Beiträge
 
Delphi 12 Athens
 
#9

AW: Pointer auf Instanz zurückgeben

  Alt 9. Mai 2022, 11:42
Zitat:
Delphi-Quellcode:
type
  TMyClass = object
  public
    Wert: integer;
    procedure Free;
  end;
Oh man... Diese Art von Object ist schon seit Jahrzehnten deprecated, das stammt noch aus den Zeiten von TurboPascal für Windows und seiner OWL library. Sollte man heutzutage wirklich nicht mehr verwenden, auch wenn Delphi den Typ noch unterstützt.
Peter Below
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Pointer auf Instanz zurückgeben

  Alt 9. Mai 2022, 12:46
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.
$2B or not $2B
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 08:41 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