AGB  ·  Datenschutz  ·  Impressum  







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

Objekt freigeben

Ein Thema von Yheeky · begonnen am 20. Jun 2008 · letzter Beitrag vom 23. Jun 2008
Antwort Antwort
Seite 1 von 2  1 2      
Yheeky

Registriert seit: 7. Jun 2002
1.339 Beiträge
 
#1

Objekt freigeben

  Alt 20. Jun 2008, 16:52
Hi,

ich habe eben ziemlich lange über einem Problem gehangen, aber es inzwischen "gelöst". Folgende Sache tritt bei meinem Projekt auf:
Ich habe ein eigenes Objekt von TObject abgeleitet (TDaten).

Ich habe nun eine Funktion, die ein solches Objekt erstellt und Daten ins Internet sendet. Abschließend wollte ich das Objekt wieder freigeben, aber genau da kam ein Fehler.

Delphi-Quellcode:
var tempAuto : TAuto;
begin
tempAuto := TAuto.Create;
tempAuto := autoSammlung.GetAutoByName('Opel');

idHTTP.Get('...');

tempAuto.Free; // <-- hier kommt eine Zugriffsverletzung. Wenn ich die Zeile rauslasse, funktioniert alles wie gewollt
end;
Auch die Variante mit try...finally hat nicht funktioniert:

Delphi-Quellcode:
var tempAuto : TAuto;
begin
tempAuto := TAuto.Create;
tempAuto := autoSammlung.GetAutoByName('Opel');

try
  idHTTP.Get('...');
finally
  tempAuto.Free; // <-- auch hier der Fehler
end;

end;
Kann mir jemand erklären, woran die Zugriffsverletzung liegt?
  Mit Zitat antworten Zitat
Benutzerbild von RavenIV
RavenIV

Registriert seit: 12. Jan 2005
Ort: Waldshut-Tiengen
2.875 Beiträge
 
Delphi 2007 Enterprise
 
#2

Re: Objekt freigeben

  Alt 20. Jun 2008, 17:07
Ein Wenig mehr Information bitte.

Wie sieht autoSammlung.GetAutoByName('Opel'); aus?
Und was passiert bei idHTTP.Get('...'); ?

Hinweise:
Vermutlich kannst / musst Du Dir das "Create" und das "Free" sparen.
Die Objekte existieren schon autoSammlung.
tempAuto ist dann nur ein Verweis auf ein Element von autoSammlung.
Klaus E.
Linux - das längste Text-Adventure aller Zeiten...
Wer nie Linux mit dem vi konfiguriert hat, der hat am Leben vorbei geklickt.
  Mit Zitat antworten Zitat
Yheeky

Registriert seit: 7. Jun 2002
1.339 Beiträge
 
#3

Re: Objekt freigeben

  Alt 20. Jun 2008, 17:20
Danke für den kleinen versteckten Hinweis Habe den Fehler gerade gefunden. Es liegt tatsächlich in der Funktion GetAutoByName, obwohl mit hier beim Debuggen kein Fehler angezeigt wird!

Erklärung anhand eines Ausschnittes der Unit:

Delphi-Quellcode:
function TAuto.getAuto(Index: Cardinal): TAuto;
begin
  Result := TAuto(inherited Items[Index]);
end;

function TAuto.GetAutoByName(Autoname: String): TAuto:
var
  I: Integer;
  tempAuto : TAuto;
begin
  result := nil;

  if Count <> -1 then
  begin
    for I := 0 to Count - 1 do
    begin
      tempAuto := TAuto(getItem(I)); // <-- hier liegt der Fehler

      if tempAuto.Name = Autoname then
      begin
        result := tempAuto;
        Exit;
      end;
    end;
  end;
end;

Anstatt getItem, welches in der Basisklasse verfügbar ist, muss ich natürlich getAuto aufrufen. Dann funktioniert es auch! Danke nochmal für den Denkanstoss! Sehr ihr, manchmal muss man garnicht viel helfen
  Mit Zitat antworten Zitat
Benutzerbild von MacGuyver
MacGuyver

Registriert seit: 9. Sep 2003
Ort: Wildeshausen
295 Beiträge
 
Turbo Delphi für Win32
 
#4

Re: Objekt freigeben

  Alt 20. Jun 2008, 17:26
Tach,

das Typecasting über TAuto(getItem(I)) ist gefährlich. Besser wäre :=getItem(I) as TAuto weil es zur Exception kommt, wenn der Typ nicht stimmt.

Stefan
Englisch eine Weltsprache? Zu kompliziert und der nahe Osten würde Englisch als Pflichtweltsprache nicht akzeptieren.
IDO wäre genau das Richtige: http://forum.idolinguo.de/index.php oder www.idolinguo.de
  Mit Zitat antworten Zitat
Yheeky

Registriert seit: 7. Jun 2002
1.339 Beiträge
 
#5

Re: Objekt freigeben

  Alt 20. Jun 2008, 18:14
Das sollte zwar relativ sicher sein, aber ist noch eine gute Ergänzung, danke!
  Mit Zitat antworten Zitat
jottkaerr

Registriert seit: 2. Jul 2007
Ort: Tuttlingen
81 Beiträge
 
Delphi 10.1 Berlin Professional
 
#6

Re: Objekt freigeben

  Alt 22. Jun 2008, 13:25
Auch wenn Du inzwischen die Methode GetAutoByName() als Schuldigen ausgemacht und korrigiert hast, stecken im folgenden Code noch zwei Fehler.

Zitat von Yheeky:
Delphi-Quellcode:
var tempAuto : TAuto;
begin
tempAuto := TAuto.Create;
tempAuto := autoSammlung.GetAutoByName('Opel');

try
  idHTTP.Get('...');
finally
  tempAuto.Free;
end;

end;
Zum einen erzeugst Du ein TAuto, aber die einzige Referenz auf dieses Objekt überschreibst Du in der nächsten Zeile sofort wieder. Somit hast Du ein Speicherleck.

Der zweite Fehler ist noch viel schwerwiegender und kann im weiteren Verlauf zu einer Zugriffsverletzung oder Ähnlichem führen. Über GetAutoByName() lässt Du dir eine Referenz auf ein Objekt geben, das Du später freigibst, ohne dass die autoSammlung etwas davon erfährt (ich gehe mal davon aus, dass sich das Objekt im Destruktor nicht bei autoSammlung abmeldet). Bei einem späteren Aufruf von GetAutoByName() kann es passieren, dass versucht wird, auf dieses nicht mehr existierende Objekt zuzugreifen (z.B. für den Namensvergleich). Und wenn autoSammlung sich auch um das Freigeben der von ihr verwalteten Objekte kümmert, wird sie irgendwann später den Destruktor ein zweites Mal aufrufen -- und dadurch in nicht mehr alloziertem Speicher wildern.

Und selbst wenn sich das TAuto-Objekt im Destruktor sauber bei autoSammlung abmeldet: Du wirst nach dem Ausführen des obigen Codes keinen Opel mehr in der Sammlung finden. Das dürfte wahrscheinlich nicht gewünscht sein.

Beheben kannst Du beide Probleme, indem Du entweder eine methode TAuto.Assign einführst, die die Propertys eines anderen TAuto-Objekts übernehmen kann:

Delphi-Quellcode:
var tempAuto : TAuto;
begin
  tempAuto := TAuto.Create;

  try
    tempAuto.Assign(autoSammlung.GetAutoByName('Opel'));
    idHTTP.Get('...');
  finally
    tempAuto.Free; // <-- auch hier der Fehler
  end;

end;
Oder Du verzichtest auf die Freigabe, denn autoSammlung kümmert sich (hoffentlich) selbst darum:

Delphi-Quellcode:
var tempAuto : TAuto;
begin
  tempAuto := autoSammlung.GetAutoByName('Opel');

  idHTTP.Get('...');
end;
Jürgen Krämer
Sometimes I think the surest sign that intelligent life exists elsewhere
in the universe is that none of it has tried to contact us. (Calvin)
  Mit Zitat antworten Zitat
Benutzerbild von RavenIV
RavenIV

Registriert seit: 12. Jan 2005
Ort: Waldshut-Tiengen
2.875 Beiträge
 
Delphi 2007 Enterprise
 
#7

Re: Objekt freigeben

  Alt 23. Jun 2008, 09:00
Zitat von jottkaerr:
Auch wenn Du inzwischen die Methode GetAutoByName() als Schuldigen ausgemacht und korrigiert hast, stecken im folgenden Code noch zwei Fehler.
Genau das wollte ich doch mit meinem Beitrag erreichen.
Aber ich wollte ihm halt nicht die komplette Lösung auf den Teller legen, sondern nur in die richtige Richtung schubsen.
Anscheînend war der Schubser nicht stark genug.
Klaus E.
Linux - das längste Text-Adventure aller Zeiten...
Wer nie Linux mit dem vi konfiguriert hat, der hat am Leben vorbei geklickt.
  Mit Zitat antworten Zitat
Yheeky

Registriert seit: 7. Jun 2002
1.339 Beiträge
 
#8

Re: Objekt freigeben

  Alt 23. Jun 2008, 15:43
@RavenIV: Nein, leider war der Schubser nicht stark genug

Danke, für die Information. Ich weiss leider noch nicht so recht Bescheid über Objekte und konnte eueren Code auch leider noch nicht ganz nachvollziehen. Hatte mir mal ein Tutorial über Objekte und Objektlisten angeschaut, aber scheinbar habe ich noch lücken. Könnt ihr mir vielleicht nochmal einen kurzen Crash-Kurs geben? Wie ist das mit Referenzen, Speicherleck, wann muss ich Objekte mit Create initialisieren, wann darf ich sie mit Free freigeben, etc...? Wäre super!
  Mit Zitat antworten Zitat
Benutzerbild von rollstuhlfahrer
rollstuhlfahrer

Registriert seit: 1. Aug 2007
Ort: Ludwigshafen am Rhein
1.529 Beiträge
 
Delphi 7 Professional
 
#9

Re: Objekt freigeben

  Alt 23. Jun 2008, 17:06
Objekte musst du mit Create initialisteren, wenn du dann diese Instanz verwenden willst. Willst du eine andere Instanz verwenden, wird diese einfach der anderen zugewiesen. Da sich Objekte wie Pointer verhalten, gibts dabei keine Probleme. Free brauchst du dann, wenn du das Objekt nicht mehr verwenden willst. Dies ist tödlich bei Objekten, die du von anderen Instanzen geholt hast, da dann auch die andere Instanz gelöscht wird.

Tipp nebenbei: Falls Free fehlschlägt, gibts ein Speicherleck. Nutze doch FreeAndNil().

Bernhard

EDIT: Eigentlich gilt: Neue Frage, neues Thema
Bernhard
Iliacos intra muros peccatur et extra!
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#10

Re: Objekt freigeben

  Alt 23. Jun 2008, 17:25
Zitat von rollstuhlfahrer:
EDIT: Eigentlich gilt: Neue Frage, neues Thema

@Fragesteller: mache für deine neue Frage bitte ein neues Thema auf. Das hat den Vorteil das du dem Thema entsprechend dem neuen Inhalt dann auch einen aussagekräftigen Titel geben kannst. Und das hat dann gleich wieder den Vorteil das man es über die Suche schneller findet wenn man das gleiche Problem hat.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  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 21:21 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