AGB  ·  Datenschutz  ·  Impressum  







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

Umgang mit Interfaces

Ein Thema von Whookie · begonnen am 5. Dez 2013 · letzter Beitrag vom 16. Dez 2013
Antwort Antwort
Benutzerbild von himitsu
himitsu

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

AW: Umgang mit Interfaces

  Alt 13. Dez 2013, 14:39
Delphi ruft z.B weiterhin lustig die Refenz-Count Methoden von Objekten auf, auch wenn das Objekt z.B. schon freigegeben wurde.
Dann liegt der Fehler aber auch bei dir.

Wenn du "referenzählende" Variablen hast, und du denen unterm Arsch weg die Objekte klaust, wovon die natürlich nichts mitbekommen,
dann können die nur davon ausgehen, daß die darin verlinkte Instanz gültig ist und es werden die Referenzen gezählt (bzw. es wird versucht).

- Entweder es wird über die Referenzzählung der Speicher freigegeben
- und wenn nicht, dann darf die Variable nicht referenzzählend sein
- oder du mußt die referenzzählende Variable auf nil setzen (unter böswilliger Umgehung der Referenzzählung), sobald du das Objekt freigibst, oder bevor die Variable freigegeben wird, bzw. bevor sie einen neuen Wert bekommt

- und es darf auch keiner mehr die "ungültige" Referenz daraus verwenden



Gleichermaßen könnte man sich darüber aufregen, dass der Compiler nicht folgendes zur Compilezeit anmeckert:
Der meckert doch?

B ist nicht initialisiert


// folgendes funktioniert problemlos, obwohl das Objekt freigeben wurde!
Die Speicherverwaltung ht den speicher aber "oftmals" noch nicht sofort freigegeben.

Das kann man aber zum Debuggen beheben.
- FastMM entsprechend einstellen
- oder einen Debug-Speichermanager verwenden

welche die Objektinstanzen zerstören/überschreiben, womit des beim nächsten Zugriff knallt


PS: Zugrif auf "ungültige" Zeiger .... wie oben erwähnt.
Das Objekt ist weg, aber DU hast den Instanzzeiger in MySomeThingObject nicht bereinigt.
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (13. Dez 2013 um 14:48 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.071 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Umgang mit Interfaces

  Alt 13. Dez 2013, 15:23
Gleichermaßen könnte man sich darüber aufregen, dass der Compiler nicht folgendes zur Compilezeit anmeckert:
Der meckert doch?

B ist nicht initialisiert


PS: Zugrif auf "ungültige" Zeiger .... wie oben erwähnt.
Das Objekt ist weg, aber DU hast den Instanzzeiger in MySomeThingObject nicht bereinigt.
Eben das wollte ich zeigen!
Solange der Pointer nicht ungültig wird, wird ja auch beliebig in die Methoden gesprungen.
Wenn hier fröhlich Interface- und Objektreferenzen gemischt werden (sollt ihr dafür alle in der Hölle schmoren) dann geht auch folgends:
Delphi-Quellcode:
function TMyDoSomething.DoSomeThing : Integer;
begin
  Result := 123;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  MySomeThingObject : TMyDoSomething;
  MagicNumber : Integer;
begin
// MySomeThingObject := TMyDoSomething.Create;
  MagicNumber := MySomeThingObject.DoSomeThing;
// MagicNumber hat jetzt den Wert 123, obwohl kein Objekt erzeugt wurde! Schwarze Magie? ;-)
end;
Von daher soll der Compiler doch ruhig in die eigenen _AddRef- und _Release-Methoden springen, wenn man meint sowas brauchen zu müssen!
  Mit Zitat antworten Zitat
Whookie

Registriert seit: 3. Mai 2006
Ort: Graz
446 Beiträge
 
Delphi 10.3 Rio
 
#3

AW: Umgang mit Interfaces

  Alt 13. Dez 2013, 18:18
Ich seh schon ... heißes Thema ...

Da es mir aber um die Implementierung mit Interfaces geht habe ich das ganze nochmals vereinfacht und komplett auf Interfaces umgestellt. Dazu gibts ein eigenes IAdmin-Interface in dem die Sachen definiert sind die vorher eben nur in der Objektinstanz zur Verfügung standen.

Die Implementierung habe ich hier angehängt weil es noch ein Problem bei der Verwaltung der Interfaces gibt und ja, ohne FastMM gibts keine vernünftige Delphi-Entwicklung !

Nochmals zur Erklärung: Die "Hauptliste" (fIntfLst) wird aus einer Textdatei erstellt, es gibt um die 20 verschiedenen Klassen die aus der Kombination von ca. 10 Interfaces bestehen. Diese "Knoten" stehen noch untereinander in Beziehung und daher speichern die Knoten diese Beziehungen in privaten Listen (wie z.B.: TTest.fMyNodes)...

Eigentlich dachte ich ja, das bei reiner Interface-Verwendung keine Probleme mehr auftreten, aber irgendwie schaffe ich es durch meine Querverlinkung die Referenzzählung durcheinander zu bringen (siehe uImpl.pas Zeile 170)...
Angehängte Dateien
Dateityp: 7z Interface_tests.7z (2,6 KB, 4x aufgerufen)
Whookie

Software isn't released ... it is allowed to escape!
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.071 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: Umgang mit Interfaces

  Alt 16. Dez 2013, 11:48
Eigentlich dachte ich ja, das bei reiner Interface-Verwendung keine Probleme mehr auftreten, aber irgendwie schaffe ich es durch meine Querverlinkung die Referenzzählung durcheinander zu bringen (siehe uImpl.pas Zeile 170)...
Mir ist nicht ganz klar, worauf das Testprogramm abzielt, aber im Anhang findest du eine Version ohne Speicherleck.
Man kann sich die TObjectList<T> und die Item-Klasse komplett sparen, aber ich merke du hast mein Beispiel mit dem Dictionary weiter oben auch nicht wirklich näher ausprobiert und/oder verstanden.

Ansonsten merkt man am Quelltext, dass du häufig viel zu kompliziert denkst und durch die Brust-ins-Auge-Lösungen bevorzugst.

Zitat von OlafSt:
Das ist mir klar, ich programmier schon ein paar Tage länger mit Delphi
Interfaces werden seit Delphi 4 unterstützt, das sind auch schon ein paar Tage länger.
Hätte man sich auch mal zwischenzeitlich mit beschäftigen können...
Angehängte Dateien
Dateityp: zip Interface_tests.zip (3,5 KB, 3x aufgerufen)

Geändert von TiGü (16. Dez 2013 um 15:26 Uhr)
  Mit Zitat antworten Zitat
OlafSt

Registriert seit: 2. Mär 2007
Ort: Hamburg
284 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#5

AW: Umgang mit Interfaces

  Alt 16. Dez 2013, 14:19
Zitat von Whookie:
Das ist mir klar, ich programmier schon ein paar Tage länger mit Delphi
Interfaces werden seit Delphi 4 unterstützt, das sind auch schon ein paar Tage länger.
Hätte man sich auch mal zwischenzeitlich mit beschäftigen können...
Wie man an meinem Vorposter sieht, war es doch nicht so verkehrt, sich lieber mit Generics oder anderen wichtigen Neuerungen zu befassen als mit dieser halblebendigen Implementation seine Zeit zu vergeuden In C# oder gar C++ wird mir das hier gelernte aber deutlich weiterhelfen.
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.190 Beiträge
 
Delphi 10 Seattle Enterprise
 
#6

AW: Umgang mit Interfaces

  Alt 16. Dez 2013, 14:30
Weak References gibt es ja schon länger auf dem "Nextgen"-Compiler. Da mich der nicht interessiert, hoffe ich seit langem darauf, dass das endlich mal für den Desktop kommt (http://www.delphipraxis.net/176352-w...-compiler.html)

Gerade auf dem Desktop versucht ja auch Emba immer bis zu Julius Caesar rückwärtskompatibel zu sein. Aber was ist mit neuen Projekten die keine Altlasten mehr unterstützen müssen?
  Mit Zitat antworten Zitat
Whookie

Registriert seit: 3. Mai 2006
Ort: Graz
446 Beiträge
 
Delphi 10.3 Rio
 
#7

AW: Umgang mit Interfaces

  Alt 16. Dez 2013, 15:02
Eigentlich dachte ich ja, das bei reiner Interface-Verwendung keine Probleme mehr auftreten, aber irgendwie schaffe ich es durch meine Querverlinkung die Referenzzählung durcheinander zu bringen (siehe uImpl.pas Zeile 170)...
Mir ist nicht ganz klar, worauf das Testprogramm abzielt, aber im Anhang findest du eine Version ohne Speicherleck.
Man kann sich die TObjectList<T> und die Item-Klasse komplett sparen, aber ich merke du hast mein Beispiel mit dem Dictionary weiter oben auch nicht wirklich näher ausprobiert und/oder verstanden.

Ansonsten merkt man am Quelltext, dass du häufig viel zu kompliziert denkst und durch die Brust-ins-Auge-Lösungen bevorzugst.
Habe ich mir angesehen, aber die Welt ist halt nicht immer so einfach wie man es sich gerne machen würde. Die Hauptliste enthält bereits einen Hash und ist danach sortiert (um effizient darauf zugreifen zu können), alle anderen Listen benötigen keinen Namen und keinen Hash sie werden beim Parsen korrekt zusammengestellt und niemals durchsucht.
Das Beispiel ist soweit reduziert, dass nur noch das wesentliche (die gegenseitige Verlinkung) zu sehen ist.

Falls Du Dir die Implementierung von TDictionary mal angesehen hast, ist das ein dynamisches Array aus Records mit HashCode, Key und Value also genau was TListData auch enthält. Wo also die Liste verwaltet wird spielt meines Erachtens nach nur eine untergeordnete Rolle. Der einzige Unterschied liegt eventuell in der etwas lahmen Suche von TDictionary...


Wenn du schon die Zitatfunktion bemühst:

Zitat von Whookie:
Das ist mir klar, ich programmier schon ein paar Tage länger mit Delphi
Interfaces werden seit Delphi 4 unterstützt, das sind auch schon ein paar Tage länger.
Hätte man sich auch mal zwischenzeitlich mit beschäftigen können...
dann versuch das mal so, dass es nicht sinnentstellend wird:

Sehe ich das richtig, ...
Wie oben erwähnt,...
Das ist mir klar, ich programmier schon ein paar Tage länger mit Delphi Ich ...
Aber ich gebe zu, soviele Einrückungen können schon ganz schön verwirrend sein
Whookie

Software isn't released ... it is allowed to escape!
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.071 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: Umgang mit Interfaces

  Alt 16. Dez 2013, 15:34
Habe ich mir angesehen, aber die Welt ist halt nicht immer so einfach wie man es sich gerne machen würde. Die Hauptliste enthält bereits einen Hash und ist danach sortiert (um effizient darauf zugreifen zu können), alle anderen Listen benötigen keinen Namen und keinen Hash sie werden beim Parsen korrekt zusammengestellt und niemals durchsucht.
Das Beispiel ist soweit reduziert, dass nur noch das wesentliche (die gegenseitige Verlinkung) zu sehen ist.

Falls Du Dir die Implementierung von TDictionary mal angesehen hast, ist das ein dynamisches Array aus Records mit HashCode, Key und Value also genau was TListData auch enthält. Wo also die Liste verwaltet wird spielt meines Erachtens nach nur eine untergeordnete Rolle. Der einzige Unterschied liegt eventuell in der etwas lahmen Suche von TDictionary...
So weit, so richtig, aber warum das Rad zweimal erfinden?
Sind denn diese anderen Listen von einen anderen (eigenen) Listentyp ohne Hash?

Und der entscheidene Unterschied ist: Ich habe keine Speicherlecks beim Beenden (laut FastMM).
Um wieviel langsamer ist denn die Suche von TDictionary im Verhältnis zu deiner Lösung?

Wenn du schon die Zitatfunktion bemühst:
Da habe ich mich vertan! Sorry, ist korrigiert!
  Mit Zitat antworten Zitat
Whookie

Registriert seit: 3. Mai 2006
Ort: Graz
446 Beiträge
 
Delphi 10.3 Rio
 
#9

AW: Umgang mit Interfaces

  Alt 16. Dez 2013, 16:47
...aber warum das Rad zweimal erfinden?
Code:
fList: TObjectList<TListData>
erfindet ja das Rad nicht neu...

Sind denn diese anderen Listen von einen anderen (eigenen) Listentyp ohne Hash?
Es ist eine einfache Liste (in der Interfacelosen-Variante vom Type TObjectList) ohne weitere Daten (der Besitzer durchläuft sie, um z.B. allen Elementen eine Nachricht zu übermitteln).

Und der entscheidene Unterschied ist: Ich habe keine Speicherlecks beim Beenden (laut FastMM).
Die habe ich auch nicht, solange es keine Quer-Referenzen gibt. Sobald aber eines der Objekte eine zusätzliche Liste pflegt (siehe Beitrag #39, uImpl.pas, Zeile 130), beginnt der Spaß mit der Referenzzählung. Ich nehme an, dass sich das - unabhängig von der verwendeten Liste - nur durch Manipulation der Referenzzählung (Beitrag 45, himitsu), wirklich lösen lässt.

Um wieviel langsamer ist denn die Suche von TDictionary im Verhältnis zu deiner Lösung?
Meine braucht im worst case log2(n) die von Delphi im Durchschnitt n/2, das sind bei 100000 Elementen 17 zu 50000 Vergleiche...


Edit: Was deine Version in #51 angeht, die hat zwar kein Speicherleck, funktioniert aber andererseits auch nicht richtig (du erzeugst zwar 4 Elemente die alle IInteger unterstützen, aber bei der Ausgabe sind es nur mehr 3....)
Whookie

Software isn't released ... it is allowed to escape!

Geändert von Whookie (16. Dez 2013 um 17:04 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Umgang mit Interfaces

  Alt 13. Dez 2013, 19:29
Wenn der Speichermanager aufräumt, dann wird es auch knallen. Oder wenn inzwischen etwas Anderes an der Stelle steht, dann produziert man damit einen Buffer-Overrun,
wenn man auf ungültige Variablen zugreift.

Und das ist nicht erst seit Interfaces so.
Delphi-Quellcode:
var
  o: TMyIrgendwas;

o := TMyIrgendwas.Create;
o.Free;
o.DoWas; // Fehler

o := TMyIrgendwas.Create;
FreeAndNil(o);
o.DoWas; // Zugriffsverletzung bei Addresse 0


Man kann gern die Speicherverwaltung komplett der Referenzzählung des Interfaces überlassen.

Und wenn es unbedingt sein muß, dann holt man sich "kurzzeitig" nochmal eine Objekt-Referenz aus dem Interface raus (an dieser Stelle muß parallel eine Interface-Referenz vorhanden sein), denn Delphi bietet seit einer Weile ein Pseudo-Interface an, welches die Objektreferenz zurückgibt. (wenn im Interface ein Delphi-Objekt steckt)
Und an diese Objektreferenz kommt man z.B. via intf AS TObject ran.
Man kann natürlich auch eigene Getter in seinem Interface verbauen, welches Objekt-Instanzen zurückgibt.
Sobald dann die "paralelle" Interface-Referenz freigegeben wird, ist die Objektreferenz als "ungültig" anzusehen.
Ein Therapeut entspricht 1024 Gigapeut.
  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 05:15 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