AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language interface und variable des implementierenden objekts

interface und variable des implementierenden objekts

Ein Thema von snook · begonnen am 11. Dez 2011 · letzter Beitrag vom 22. Dez 2011
Antwort Antwort
Seite 2 von 2     12
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.429 Beiträge
 
Delphi 10.4 Sydney
 
#11

AW: interface und variable des implementierenden objekts

  Alt 20. Dez 2011, 09:40
Ein untypisierter Parameter für die Rückgabe eines Interface scheint mir sehr verdächtig.
Wird hier eventuell die Referenzzählung ausgetrickst?
Warum nicht so:
Delphi-Quellcode:
procedure TCustomDataModule.GetLink(out Link: IDataChangeLink);
begin
  Link := FLink;
end;
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: interface und variable des implementierenden objekts

  Alt 20. Dez 2011, 10:24
Warum nicht so:
Delphi-Quellcode:
procedure TCustomDataModule.GetLink(out Link: IDataChangeLink);
begin
  Link := FLink;
end;
Untypisch nicht, nahezu alle WMI-Implementationen machen sowas, für die Rückgabe der Werte.

Und das Ergebnis des Ganzen?
Speicherlecks.

Denn ist vorher schon was in dem Link-Parameter drin, dann wird es ignoriert und nicht freigegeben.
Für eine automatische Referenzzählung ist das OUT hier also der nahezu sichere Tot.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

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

AW: interface und variable des implementierenden objekts

  Alt 20. Dez 2011, 13:17
Und das Ergebnis des Ganzen?
Speicherlecks.

Denn ist vorher schon was in dem Link-Parameter drin, dann wird es ignoriert und nicht freigegeben.
Für eine automatische Referenzzählung ist das OUT hier also der nahezu sichere Tot.
Bis zu welcher Delphiversion bestand denn dieser Fehler seinerzeit? (bei XE und XE2 jedenfalls nicht mehr)

// EDIT:
Nicht einmal bei Delphi 2007 passiert das bei mir.
// EDIT2:
Und auch bei Delphi 3 nicht.

Das heißt so allgemein lässt sich das auf jeden Fall nicht sagen. Ich bekomme das nicht hin, dass das Problem auftritt.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!

Geändert von jaenicke (20. Dez 2011 um 13:25 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: interface und variable des implementierenden objekts

  Alt 20. Dez 2011, 15:02
OUT-Parameter sind Ausgabeparameter und da werden Eingangswerte nicht beachtet.
Dieses Problem sollte also immernoch bestehen.

Wenn nicht und Emba hat dieses Verhalten geändert, dann ist das ein Bug und Emba hat das gefälligst wieder auszubauen.
"Böse" ist eigentlich, daß der Eingangswert des Ausgangsparameters beachtet wird, was eigentlich nicht gemacht werden dürfte.

const/in = in ... ingibt es in Delphi nicht, aber es entspricht quasi dem Parameter ohne eine Angabe von var/out/const
var = in&out
out = out

Gut, Delphi scheint das Interface die Variable, vor Übergabe an den OUT-Parameter, freizugeben.
Letzteres SetOutI müßte in etwa das tun, was diese WMI-Schnittstelle macht ... also den Eingangsparameter zu ignorieren.
Was sagt denn ein älteres Delphi zu dem Code?
Delphi-Quellcode:
type
  TTestIntf = class(TInterfacedObject, IInterface)
    FStrings: TStrings;
    constructor Create(SL: TStrings);
    destructor Destroy; override;
  end;

constructor TTestIntf.Create(SL: TStrings);
begin
  inherited Create;
  FStrings := SL;
  FStrings.Add('TTestIntf.Create ' + IntToHex(Integer(Self), 8));
end;

destructor TTestIntf.Destroy;
begin
  FStrings.Add('TTestIntf.Destroy ' + IntToHex(Integer(Self), 8));
  inherited;
end;

procedure TForm6.SetVar(var Intf: IInterface);
begin
  Memo1.Lines.Add('SetVar begin');
  Intf := TTestIntf.Create(Memo1.Lines);
  Memo1.Lines.Add('SetVar end');
end;

procedure TForm6.SetOut(out Intf: IInterface);
begin
  Memo1.Lines.Add('SetOut begin');
  IInterface(Intf) := TTestIntf.Create(Memo1.Lines);
  Memo1.Lines.Add('SetOut end');
end;

procedure TForm6.SetVarD(var Intf);
begin
  Memo1.Lines.Add('SetVarD begin');
  IInterface(Intf) := TTestIntf.Create(Memo1.Lines);
  Memo1.Lines.Add('SetVarD end');
end;

procedure TForm6.SetOutD(out Intf);
begin
  Memo1.Lines.Add('SetOutD begin');
  IInterface(Intf) := TTestIntf.Create(Memo1.Lines);
  Memo1.Lines.Add('SetOutD end');
end;

procedure TForm6.SetOutI(out Intf);
var
  I: IInterface;
begin
  Memo1.Lines.Add('SetOutI begin');
  I := TTestIntf.Create(Memo1.Lines);
  I._AddRef;
  Pointer(Intf) := Pointer(I);
  Memo1.Lines.Add('SetOutI end');
end;

var Intf: IInterface;

Memo1.Lines.Add('');
Memo1.Lines.Add('create test-interface');
Intf := TTestIntf.Create(Memo1.Lines);
Memo1.Lines.Add('call SetVar');
SetVar(Intf);
Memo1.Lines.Add('set nil');
Intf := nil;

Memo1.Lines.Add('');
Memo1.Lines.Add('create test-interface');
Intf := TTestIntf.Create(Memo1.Lines);
Memo1.Lines.Add('call SetOut');
SetOut(Intf);
Memo1.Lines.Add('set nil');
Intf := nil;

Memo1.Lines.Add('');
Memo1.Lines.Add('create test-interface');
Intf := TTestIntf.Create(Memo1.Lines);
Memo1.Lines.Add('call SetVarD');
SetVarD(Intf);
Memo1.Lines.Add('set nil');
Intf := nil;

Memo1.Lines.Add('');
Memo1.Lines.Add('create test-interface');
Intf := TTestIntf.Create(Memo1.Lines);
Memo1.Lines.Add('call SetOutD');
SetOutD(Intf);
Memo1.Lines.Add('set nil');
Intf := nil;

Memo1.Lines.Add('');
Memo1.Lines.Add('create test-interface');
Intf := TTestIntf.Create(Memo1.Lines);
Memo1.Lines.Add('call SetOutI');
SetOutI(Intf);
Memo1.Lines.Add('set nil');
Intf := nil;
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (20. Dez 2011 um 15:40 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

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

AW: interface und variable des implementierenden objekts

  Alt 20. Dez 2011, 16:27
Gut, Delphi scheint das Interface die Variable, vor Übergabe an den OUT-Parameter, freizugeben.
Ja, so muss es ja sein, es ist ja schließlich ein out-Parameter, das heißt der Aufruf entspricht einer Neuzuweisung. Also muss das alte Objekt natürlich vorher freigegeben werden.

Was sagt denn ein älteres Delphi zu dem Code?
Delphi 3 sagt:
Code:
create test-interface
TTestIntf.Create 008A3738
call SetVar
SetVar begin
TTestIntf.Create 008A3750
TTestIntf.Destroy 008A3738
SetVar end
set nil
TTestIntf.Destroy 008A3750

create test-interface
TTestIntf.Create 008A3738
call SetOut
TTestIntf.Destroy 008A3738
SetOut begin
TTestIntf.Create 008A3738
SetOut end
set nil
TTestIntf.Destroy 008A3738

create test-interface
TTestIntf.Create 008A3738
call SetVarD
SetVarD begin
TTestIntf.Create 008A3750
TTestIntf.Destroy 008A3738
SetVarD end
set nil
TTestIntf.Destroy 008A3750

create test-interface
TTestIntf.Create 008A3738
call SetOutD
TTestIntf.Destroy 008A3738
SetOutD begin
TTestIntf.Create 008A3738
SetOutD end
set nil
TTestIntf.Destroy 008A3738

create test-interface
TTestIntf.Create 008A3738
call SetOutI
TTestIntf.Destroy 008A3738
SetOutI begin
TTestIntf.Create 008A3738
SetOutI end
set nil
TTestIntf.Destroy 008A3738
Ich würde mal sagen alles ok, oder?
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
10.934 Beiträge
 
Delphi 12 Athens
 
#16

AW: interface und variable des implementierenden objekts

  Alt 20. Dez 2011, 17:06
Gut, Delphi scheint das Interface die Variable, vor Übergabe an den OUT-Parameter, freizugeben.
Ja, so muss es ja sein, es ist ja schließlich ein out-Parameter, das heißt der Aufruf entspricht einer Neuzuweisung. Also muss das alte Objekt natürlich vorher freigegeben werden.
Wenn du einen Interface-Parameter als out deklarierst, wird vor dem Aufruf der Methode ein IntfClear gemacht. Damit wird ein eventuell vorher in dem Parameter gespeichertes Interface freigegeben. Das erfolgt im der aufgerufenen Methode übergeordneten Kontext. Damit ist der out-Pramater innerhalb der Methode bereits mit nil vorbelegt, wie es auch für lokale Interface-Variablen gilt.

Ich kann da ebensowenig ein Fehlverhalten des Compilers erkennen.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
snook

Registriert seit: 25. Jun 2010
94 Beiträge
 
Delphi 2005 Professional
 
#17

AW: interface und variable des implementierenden objekts

  Alt 21. Dez 2011, 23:16
in etwa so hatte ich das auch verstanden & beim debuggen auch gesehen. ich dachte halt, dies ist der sicherste weg die referenzzählung am leben zu halten, selbst wenn man ma ne interfacevariable übergibt die noch belegt ist.

aber hat jetzt jemand von euhc auch mal dieses mysteriöse verhalten das ich anfangs beschrieben hatte bemerkt? oder etwas ähnliches, dass sich im schlimmsten fall nur durch einen neustart des gesamten computers beheben lässt? ich habe damit wirklich ein problem dass ich so nicht lösen kann, insbesondere da dritte mit diesem programm arbeiten sollen und es im moment auch schon tun und es einfach nicht sein kann, dass in manchen momenten (soweit ich das beurteilen kann nicht vorhersehbar) wertezuweisungen einfach verworfen werden...

falls nicht, kennt jemand möglichkeiten, wie man solchen problemen auf den grund gehen kann??? es kann ja durchaus meine eigene dummheit an irgendeiner anderen stelle sein...

Geändert von snook (21. Dez 2011 um 23:24 Uhr)
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.429 Beiträge
 
Delphi 10.4 Sydney
 
#18

AW: interface und variable des implementierenden objekts

  Alt 22. Dez 2011, 10:56
Erstell ein Minimalprojekt, bei dem der Fehler auftritt und entferne so lange Teile, bis der Fehler nicht mehr auftritt.
Wenn du nicht weiter kommst, stellst du die Quellen für das Minimalprojekt hier rein.
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 12:36 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