Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi TObjectList.Free erzeugt AV (https://www.delphipraxis.net/183819-tobjectlist-free-erzeugt-av.html)

SvB 6. Feb 2015 17:01

Delphi-Version: XE7

TObjectList.Free erzeugt AV
 
Ich stehe gerade etwas auf dem Schlauch und würde mich über eine Tipp freuen.

Ich habe eine TObjectList mit OwnObjects = True. In der Liste sind mehrere Objekte angefügt.
Jetzt hab ich das Problem, dass ein Objekt an anderer Stelle schon frei gegeben wurde und
ObjectList.Free eine Exception auslöst, da das eine Objekt nicht mehr existiert.

Jetzt möchte ich vor dem ObjectList.Free prüfen, ob die Objekte in der Liste noch gültig sind und ungültige aus der Liste entfernen.
Ich hab nur gerade ein Brett vorm Kopf, wie ich das abfrage. Wer kann helfen?

BadenPower 6. Feb 2015 17:42

AW: TObjectList.Free erzeugt AV
 
Wenn Du eine TObjectList hast, bei der die Liste der Eigentümer der Objekte ist, dann solltest Du auch das Freigeben der Objekte der Liste überlassen und die nicht selbst irgendwo freigeben ohne es der Liste mitzuteilen.

Der Schlüssel zum Erfolg liegt bei:

Delphi-Quellcode:
TObjectList.Remove(AObject: TObject);

Sir Rufo 6. Feb 2015 17:47

AW: TObjectList.Free erzeugt AV
 
Das ist doch einfach: Es geht schlicht und ergreifend nicht.

Du hast die Verwaltung der Lifetime der Instanz an die Liste gegeben und nun schmeisst du es irgendwo aus dem Speicher. Das macht man nicht.

Das ist so, als ob du mir etwas schenkst und dann mir wieder wegnimmst. Das gibt auch Mecker (mindestens).

Nur das es bei Referenzen eben schlecht mit dem Kontrollieren aussieht, ob da an der Referenz noch etwas liegt. Denn der Speicher ist noch da (du klaust ja keinen RAM-Riegel aus dem System) und da kann auch noch irgendwas stehen. Es gibt also keine zuverlässige Möglichkeit zu prüfen ob unter der Referenz noch eine gültige Instanz zu finden ist.

Mach es anders und alles wird gut.

SvB 6. Feb 2015 18:05

AW: TObjectList.Free erzeugt AV
 
OK, hatte gehofft, das man das prüfen kann. Dann mach ich anders, ist auch kein Problem.
Danke Euch für die Infos.

jaenicke 6. Feb 2015 18:25

AW: TObjectList.Free erzeugt AV
 
Wenn du anderswo ein entsprechendes eigenes Objekt zum Freigeben benötigst, kannst du ja eine Kopie erstellen. Alles andere wäre nicht sauber.

Eine mögliche Alternative wären Interfaces.

himitsu 6. Feb 2015 19:10

AW: TObjectList.Free erzeugt AV
 
Wenn die Objekte nachfahren von TComponent sind, dann kann man deren Messagesystem benutzen und das Objekt sich selber aus der Liste löschen lassen, wenn es freigegeben wird.
Quasi eine TComponentList mit AutoRemove.

Ab XE wäre das auch für alle anderen Nicht-TComponents relativ leicht möglich und davor bissl schwerer, aber ist nicht wirklich schön, sowas umzusetzen.

SvB 6. Feb 2015 19:56

AW: TObjectList.Free erzeugt AV
 
Ich glaube ich habe mich da etwas verrannt. Nach weiteren Überlegungen passen meine Idee und mein Ansatz dann doch nicht so ganz.

Ich arbeite schon mit einem TInterfacedObject, in dem die TObjectList enthalten ist.
In einem Formular erzeuge ich im OnCreate noch andere benötigte Formulare, deren Referenz ich in der TObjectList ablege, damit die auf jeden Fall aufgeräumt werden, falls es mal krachen sollte.
Die Unterformulare habe ich auf Position = poOwnerFormCenter eingestellt, und wollte die dann schön zentriert über dem Hauptformular anzeigen lassen. Das funktioniert nur, wenn die Unterformulare mit Owner = Hauptformular erzeugt werden.
Wenn ich dann das Hauptformular schließe, dann werden durch den Owner auch die Unterformulare aufgeräumt und danach wird Interfaced ObjectList automatisch aufgeräumt und es gibt die Exception.

Das zentrieren lasse ich jetzt, ich glaube, das war so ein Hirngespinst in das ich mich hineingesteigert habe und nicht wirklich brauche.
Ich glaube, ich werde die Unterformulare auch erst dann erzeugen, wenn ich sie brauche. Sie werden nicht immer alle benötigt und sind nicht sehr umfangreich. Das Erzeugen wird nach Bedarf dann auch schnell gehen.

Sir Rufo 6. Feb 2015 20:03

AW: TObjectList.Free erzeugt AV
 
Warum sagst du denn nicht gleich, dass es sich um Nachfahren von
Delphi-Quellcode:
TComponent
handelt, die du in der Liste speichern möchtest. :wall:

Gerade die senden dir nach Anmeldung eine Nachricht, wenn die sich aus dem Speicher entfernen.
Delphi-Referenz durchsuchenTComponent.FreeNotification
Delphi-Referenz durchsuchenTComponent.RemoveFreeNotification
Fliegt also so eine Instanz weg, ohne dass du die aus der Liste nimmst, dann wirf die einfach aus der Liste raus
Delphi-Quellcode:
CompList.OwnsObjects := False;
try
  CompList.Remove( AComponent );
finally
  CompList.OwnsObjects := True;
end;

BadenPower 6. Feb 2015 20:31

AW: TObjectList.Free erzeugt AV
 
Zitat:

Zitat von Sir Rufo (Beitrag 1289071)
Delphi-Quellcode:
CompList.OwnsObjects := False;
try
  CompList.Remove( AComponent );
finally
  CompList.OwnsObjects := True;
end;

Wenn Du "CompList.Extract( AComponent )" nimmst, dann brauchst Du .OwnObjects nicht zu verändern und auch den "try finally" - Block kannst Du Dir sparen.

Sir Rufo 6. Feb 2015 20:37

AW: TObjectList.Free erzeugt AV
 
Zitat:

Zitat von BadenPower (Beitrag 1289074)
Zitat:

Zitat von Sir Rufo (Beitrag 1289071)
Delphi-Quellcode:
CompList.OwnsObjects := False;
try
  CompList.Remove( AComponent );
finally
  CompList.OwnsObjects := True;
end;

Wenn Du "CompList.Extract( AComponent )" nimmst, dann brauchst Du .OwnObjects nicht zu verändern und auch den "try finally" - Block kannst Du Dir sparen.

Stimmt, kam mir doch gleich so komisch vor :mrgreen:

SvB 6. Feb 2015 20:52

AW: TObjectList.Free erzeugt AV
 
Sorry, ich bin nicht der 100%ige Delphi-Crack.

Wenn ich das jetzt richtig verstanden habe, dann müsste ich ja sinnvollerweise meine TObjectList informieren, wenn irgendein TComponent entfernt wird, damit es dann aus der Liste fliegt. Vielleicht ist es jetzt auch einfach zu spät.

Ne, anders. Damit das mit FreeNotification funktioniert (TComponent), müsste ich das in mein Hauptformular implementieren, in dem ich die Unterformulare in die Liste stecke und dort dann im OnFreeNotification es aus der Liste entferne. (oder so ähnlich)

Ja, ich glaube, ich habs so langsam verstanden. Das schaue ich mir aber morgen noch mal genau an. Jetzt ist erst mal Feierabend.

Sir Rufo 6. Feb 2015 20:56

AW: TObjectList.Free erzeugt AV
 
Delphi-Referenz durchsuchenTComponent.Notification überschreiben und
Delphi-Quellcode:
Operation
beachten ;)

himitsu 7. Feb 2015 03:15

AW: TObjectList.Free erzeugt AV
 
Delphi-Quellcode:
type
  TComponentList<T: TComponent> = class(TObjectList<T>)
  private type
    TNotify = class(TComponent)
      FParent: TComponentList<T>;
      procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    end;
  private
    FNotify: TNotify;
  protected
    procedure Notify(const Value: T; Action: TCollectionNotification); override;
  public
    destructor Destroy; override;
  end;

destructor TComponentList<T>.Destroy;
begin
  FNotify.Free;
  inherited;
end;

procedure TComponentList<T>.Notify(const Value: T; Action: TCollectionNotification);
begin
  inherited;
  if not Assigned(FNotify) then begin
    FNotify := TNotify.Create(nil);
    FNotify.FParent := Self;
  end;
  if Action = cnAdded then
    FNotify.FreeNotification(Value)
  else if not Contains(Value) then
    FNotify.RemoveFreeNotification(Value);
end;

procedure TComponentList<T>.TNotify.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited;
  if (Operation = opRemove) and not FParent.Contains(AComponent) then
    while FParent.Extract(AComponent) <> nil do ;
end;
Aber wenn man sowieso schon eine Owner- oder Parent-Beziehung hat, dann kann man sich eigentlich auch die zusätzliche Liste sparen, indem man die bereits existierenden Parent.Components- oder Parent.Controls-Listen mit benutzt.


Das Einzige, was ich mich bei Entwicklung dieser Liste gefragt hatte ..... wer zum Teufel war so wirklich saudämlich und hat vergessen das TList<T>.Create(), oder besser schon TEnumerable<T>.Create(), als virtual zu deklarieren, so daß man in Nachfahren ständig immer alle Konstrutoren überschreiben muß, wenn man da drin irgendwas initialisieren wöllte. :wall:

Ach ja, und wer bei den FreeNotifications keine Registrierungszählung implementierte ... mehrere Verbindungen zwischen den selben Komponenten und man muß mit dem RemoveFreeNotification aufpassen.

Genau deswegen setzte ich gern eine gekapselte Notify-Komponente ein, wenn ich nicht kontrollieren kann, ob zwischen referenzierenden Komponenten eventuell noch andere Referenzen, wie z.B. die Parent- oder Owner-Beziehungen existieren könnten.
Alternativ könnte man nur registrieren (FreeNotification) und dürfte nie deregistrieren (RemoveFreeNotification), außer mal selber wird freigegeben, aber dann räumt sich das eh von selber auf.

Sir Rufo 7. Feb 2015 08:08

AW: TObjectList.Free erzeugt AV
 
@himitsu

Und warum überschreibst du nicht Delphi-Referenz durchsuchenTObject.AfterConstruction?

jaenicke 7. Feb 2015 08:28

AW: TObjectList.Free erzeugt AV
 
Zitat:

Zitat von himitsu (Beitrag 1289101)
Das Einzige, was ich mich bei Entwicklung dieser Liste gefragt hatte ..... wer zum Teufel war so wirklich saudämlich und hat vergessen das TList<T>.Create(), oder besser schon TEnumerable<T>.Create(), als virtual zu deklarieren, so daß man in Nachfahren ständig immer alle Konstrutoren überschreiben muß, wenn man da drin irgendwas initialisieren wöllte. :wall:

Da hätte noch viel mehr virtuell deklariert werden müssen, auch bei den anderen generischen Standardklassen...
Ich überschreibe in so einem Fall meistens AfterConstruction und BeforeDestruction, was ja seit Delphi 4 für diesen Zweck existiert (wenn etwas nicht im Konstruktor gemacht werden kann)...

// EDIT:
Ja, genau... ich hatte die Antwortbox dank meines Sohnes wohl etwas zu lange offen. :D

himitsu 7. Feb 2015 11:34

AW: TObjectList.Free erzeugt AV
 
Nja. Dafür gibt es so eine Methode weniger. :oops:

Aber mal ganz im Ernst, nun weil das nicht virtuell ist, haben die in TObjectList alle drei Konstructoren überschreiben müssen, obwohl es gereicht hätte, das Neue im nur Create() zu machen, da in den anderen zwei Konstructoren nichts anderes drin steht.

Delbor 7. Feb 2015 11:41

AW: TObjectList.Free erzeugt AV
 
Hi zusammen

Hab ich das jetzt richtig gelesen? Du erzeugst Unterformulare und weist diesen deine Hauptform als Eigner Zu?
Zitat:

Die Unterformulare habe ich auf Position = poOwnerFormCenter eingestellt, und wollte die dann schön zentriert über dem Hauptformular anzeigen lassen. Das funktioniert nur, wenn die Unterformulare mit Owner = Hauptformular erzeugt werden.
Wenn ich dann das Hauptformular schließe, dann werden durch den Owner auch die Unterformulare aufgeräumt und danach wird Interfaced ObjectList automatisch aufgeräumt und es gibt die Exception.
Wenn das Hauptformular beendet wird, räumt es seine Unterformulare auf. Du hast nun mehrere Möglichkeiten:
  • Setze die Vorschläge meiner Vorredner um
  • Setze Ownerobject der Liste auf False
  • Schmeiss diie Liste raus, wenn du da keine weiteren Objcte ablegst, ansonsten
  • fügst du der Liste die Unterformulare nicht hinzu

Gruss
Delbor

Sir Rufo 7. Feb 2015 11:49

AW: TObjectList.Free erzeugt AV
 
Wenn es nur um das Aufräumen geht, dann braucht man die Liste nicht, für andere Dinge schon ;)

Delbor 7. Feb 2015 12:11

AW: TObjectList.Free erzeugt AV
 
Hi Sir Rufo

Schon klar - eine einzige solche Liste kann mehrere dutzend(?) Zeilen Quelltext einsparen .

Gruss
Delbor

SvB 7. Feb 2015 12:34

AW: TObjectList.Free erzeugt AV
 
Moin,

neuer Tag neues Glück und die Sonne scheint, da kann es ja nur besser werden.

Meine Idee hinter der ObjectList (Interface) ist, dass auf jeden Fall beim schließen des Hauptformulars alles aufgeräumt wird. Es sind nicht nur die Unterformulare, sondern auch andere Objekte wie Stringlisten, die in der ObjectList liegen. Falls mal, was auch immer, passiert, soll aufgeräumt werden. Die Anwender erzählen einem ja nicht immer alles, oder man selbst hat beim programmieren irgend einen Mist gebaut.
Bisher war es kein Problem, die Objekte in die Liste zu schieben.

Nun, jetzt wollte ich die schöne Funktion Position = poOwnerFormCenter für die Unterformulare verwenden, die jedoch mit einem Owner erzeugt werden müssen, damit das funktioniert. Das gab dann natürlich das Problem mit den 2 Ownern, einmal Hauptformular und einmal Liste. Deshalb die AV durch die Liste, weil das Hauptformular schon früher aufgeräumt hat.

Nach dem ich mal ne Nacht drüber geschlafen habe, habe ich mich fürs Erste für folgende Lösung entschieden:
Es bleibt erst mal alles in der Liste, und die räumt später auf.
Und ich habe mir einen ClassHelper geschrieben:
Delphi-Quellcode:
TShowModalCenter = class helper for TForm
  procedure ShowModalCenter(ACenterForm: TForm);
end;

procedure TShowModalCenter.ShowModalCenter(ACenterForm: TForm);
var
  X, Y: Integer;
begin
  X := ((ACenterForm.Width - Width) div 2) + ACenterForm.Left;
  Y := ((ACenterForm.Height - Height) div 2) + ACenterForm.Top;
  if X < Screen.DesktopLeft then
    X := Screen.DesktopLeft;
  if Y < Screen.DesktopTop then
    Y := Screen.DesktopTop;
  SetBounds(X, Y, Width, Height);
  ShowModal;
end;
Die Unterformulare rufe ich jetzt nicht mehr nur einfach mit ShowModal auf, sondern mit ShowModalCenter(Hauptform) und habe erst mal das erreicht was ich eigentlich wollte.

Eure Infos und Ideen muss ich mir aber auch noch mal durch den Kopf gehen lassen. Hab da im Moment nicht so viel Zeit, muss am Montag ne erste Version abliefern und hübsch kann ichs danach noch machen.

jaenicke 7. Feb 2015 12:41

AW: TObjectList.Free erzeugt AV
 
Das Aufräumen sollte immer dort passieren, wo das Objekt auch erstellt wurde. Wenn du eine TStringList im Konstruktor eines Objekts erstellst, sollte diese auch im Destruktor freigegeben werden. Sprich das Objekt, zu dem die Liste gehört, ist auch dafür verantwortlich. Natürlich musst das Objekt, das die Liste enthält, z.B. das Formular, auch freigegeben werden, damit das funktioniert. Und so geht es weiter bis zur obersten Ebene, bei der es kein übergeordnetes Objekt mehr gibt.

Aber das ist eine der wichtigsten Prinzipien der objektorientierten Programmierung. Dass du dich nicht in Verantwortlichkeiten anderer Objekte einmischst und so Kreuzbeziehungen usw. erzeugst.

Wenn du eine einzige Liste führst, in das du diverse Objekte wirfst /werfen musst, nur damit diese freigegeben werden, ist das keine gute Struktur.

SvB 7. Feb 2015 12:46

AW: TObjectList.Free erzeugt AV
 
Musste den Code gerade noch mal etwas anpassen:
Delphi-Quellcode:
TShowModalCenter = class helper for TForm
  function ShowModalCenter(ACenterForm: TForm): Integer;
end;

function TShowModalCenter.ShowModalCenter(ACenterForm: TForm): Integer;
var
  X, Y: Integer;
begin
  X := ((ACenterForm.Width - Width) div 2) + ACenterForm.Left;
  Y := ((ACenterForm.Height - Height) div 2) + ACenterForm.Top;
  if X < Screen.DesktopLeft then
    X := Screen.DesktopLeft;
  if Y < Screen.DesktopTop then
    Y := Screen.DesktopTop;
  SetBounds(X, Y, Width, Height);
  Result := ShowModal;
end;

Sir Rufo 7. Feb 2015 12:57

AW: TObjectList.Free erzeugt AV
 
So eine ich beuge mal vor allem irgendwie vor Funktion ist absoluter Overkill und führt nur zu einem unsauberen Programmierstil. Wird ja immer alles so schön aufgeräumt am Schluss.

Gut im normalen Betrieb dauert es ca. 1h bis der Speicher überläuft, aber wir haben keinen MemLeak - dann ist doch alles gut, oder etwa nicht?

Ein super Anti-Beispiel ist die FireMonkey ListBox aus XE7. Füll da mal so 10.000 Elemente rein (ist nur damit man auch was sieht) und dann gemütlich durch die Liste scrollen - rauf und runter. Toll, geht, aber was sagt der TaskManager zum Thema Speicherbedarf: Der wächst und wächst und wächst ... mit jedem Scrollen und hört einfach nicht auf. Es gibt aber keinen MemLeak, denn alles wird am Ende ja brav aufgeräumt. Dort jetzt den Fehler zu finden ist aufwändig. Bei einem MemLeak schaue ich mir die Instanzen an, wo es die meisten Leaks gibt und verfolge, wer die erzeugt und schwupps bin ich an der fehlerhaften Stelle.

So habe ich die MemLeaks in dem RestResponseDatasetAdapter gefunden und ausgemerzt.

Diese Art und Weise der Programmierung ist ähnlich schlimm, wie das paranoide Exception fangen. Lasst euch doch die Exceptions (so früh wie möglich) und die Leaks um die Ohren fliegen, dann wisst ihr wenigstens, wo es noch etwas zu tun gibt (sozusagen als automatischer ToDo-Eintrag).

Falls es nicht bekannt sein sollte: Wenn sich die Anwendung beendet wird auch der gesamte Speicher der Anwendung freigegeben, ob Leak oder nicht, es bleibt nichts zurück.

SvB 7. Feb 2015 13:27

AW: TObjectList.Free erzeugt AV
 
@Sir Rufo:
Du hast schon recht, verstehe ich. Das steht auch noch das ein oder andere auf meiner ToDo Liste. Ich hab nur gerade das Problem, dass ich mit meinem Projekt etwas hinten dran bin und der Kunde schon jammert, dass er jetzt mal was sehen will. Auch wenns im Moment für den ein oder anderen QuickAndDirty ist, ich muss mal was fertig bekommen. Übrigens: dem Kunden ist es egal wie es programmiert ist, der will klicki bunti was schönes haben.

Die andere Sache ist die, dass Du beim Testen niemals alles ausmerzen kannst. Man klickt halt anders rum, wie das ein Anwender tut. Hab ja schon MadExcept im Projekt und den Anwendern gesagt, die sollen mir den erzeugten Bericht senden, wenn eine Meldung kommt. Das machen aber vielleicht nur 30%, die anderen klicken immer weg und jammern hinterher, das Programm wäre ja Mist oder so ähnlich.

Mit den Exception-Berichten hangele ich mich dann schon Stück für Stück an das Problem. try except nutze ich so gut wie gar nicht, ich bin schon bemüht ordentlich zu coden. Es soll Rund laufen, der Anwender soll zufrieden sein, dann ist auch der GF vom Kunden zufrieden. So ist der Plan.

Auch wenn ich jetzt vielleicht wieder geschlagen werden: Ich nutze manchmal das System, was hier beschrieben wird und dieser Beitrag basiert auf diesem Interface mit OjectList.
Ich finde das in manchen Fällen ganz Nett und hilfreich, verkürzt den Code, man kanns auch oft besser lesen, weils nicht so viel verschachtelt ist. Hilfmittel finde ich immer gut, sonst würde ich ja in Assembler programmieren.

Meine ToDo Liste hat noch einige Punkte, aber eins nach dem anderen. Einer davon ist, dass ich die Exception Berichte im Hintergrund automatisch gesendet bekomme, dass ich dann handeln kann.

jaenicke 8. Feb 2015 18:11

AW: TObjectList.Free erzeugt AV
 
Zitat:

Zitat von Sir Rufo (Beitrag 1289128)
Falls es nicht bekannt sein sollte: Wenn sich die Anwendung beendet wird auch der gesamte Speicher der Anwendung freigegeben, ob Leak oder nicht, es bleibt nichts zurück.

Das stimmt so nicht. Wenn Systemressourcen reserviert wurden, werden zwar die meisten auch automatisch aufgeräumt, aber nicht alle. In einem solchen Fall war es dann so, dass das Programm zwar problemlos ein paarmal lief, aber nach dem etwa 30. Durchlauf das Betriebssystem (in dem Fall XP) insgesamt nicht mehr richtig reagierte...
Mit Vista und Windows 7 hat sich da zwar einiges getan, aber ganz aus der Welt ist das Problem AFAIK dennoch nicht.

Sir Rufo 8. Feb 2015 18:59

AW: TObjectList.Free erzeugt AV
 
Zitat:

Zitat von jaenicke (Beitrag 1289228)
Zitat:

Zitat von Sir Rufo (Beitrag 1289128)
Falls es nicht bekannt sein sollte: Wenn sich die Anwendung beendet wird auch der gesamte Speicher der Anwendung freigegeben, ob Leak oder nicht, es bleibt nichts zurück.

Das stimmt so nicht. Wenn Systemressourcen reserviert wurden, werden zwar die meisten auch automatisch aufgeräumt, aber nicht alle. In einem solchen Fall war es dann so, dass das Programm zwar problemlos ein paarmal lief, aber nach dem etwa 30. Durchlauf das Betriebssystem (in dem Fall XP) insgesamt nicht mehr richtig reagierte...
Mit Vista und Windows 7 hat sich da zwar einiges getan, aber ganz aus der Welt ist das Problem AFAIK dennoch nicht.

Full ack, ich hatte auch noch überlegt, ob ich das noch mit anspreche, habe mich aber dagegen entschieden. Manchmal muss man reduzieren, sonst sieht man den Wald vor lauter Bäumen nicht. Solche Ressourcen sollte man über ein selbstzerstörendes Interface reservieren :)

himitsu 8. Feb 2015 20:51

AW: TObjectList.Free erzeugt AV
 
Und selbst wenn Vieles inzwischen automatisch freigegeben wird.

Früher gab es in Windows nur einen großen Arbeitsspeicher, in dem alle Programme rumschrieben.
Die Nachteile kennen wir:
  • Ein Speicherleck im Programm blieb für immer bestehen, auch nach Ende des Programms.
  • Ein Buffer-Overflow konnte nicht nur eigenen Speicher zerstören, sondern auch den von anderen Programmen oder gar vom Windows selber.
  • ...

Und nun hat man nur durch Aufräumen die Möglichkeit, später auch achzusehn, ob man irgendwo was vergessen hat
und kann somit eventuell später Programmteile problemloser wiederverwenden.

Das Resultat sieht man am Delphi, denn im Commandline-Compiler war es nicht schlimm, aber im Inline-Compiler sah man die Auswirkungen der Speicherlecks, denn auch nach dem Compilieren verstopfte es die IDE immer mehr.


Und nur weil man jetzt denkt, daß etwas sowieso bis zum Programmende benötigt wird und man denkt "ach egal, Windows räumt schon auf", wer weiß was in Zukunft mal ist.
Wenn schon, dann sollte man immer ordentlich arbeiten. (PS: siehe Signatur)

Sir Rufo 8. Feb 2015 21:24

AW: TObjectList.Free erzeugt AV
 
Momentchen a mal,

ich schreibe meine Programme immer mit
Delphi-Quellcode:
ReportMemoryLeaksOnShutdown := true;
. Dann weiß ich, dass ich vergessen habe, irgendwo etwas korrekt freizugeben.

Wenn ich jetzt aber irgendeine sonstwas Sammelliste im Programm habe, die alle Instanzen aufnimmt und dann am Ende garantiert freigibt, dann habe ich beim Beenden keine MemLeaks. Toll, ich bin ein Held!

Oder doch nur der größte Tor von allen?

Plötzlich melden sich auf einmal die Benutzer, weil nach 2-5h Betrieb der Anwendung ein Speicherfehler kommt: "Arbeitsspeicher voll!"

Und warum? Denken, verstehen, handeln. Dann auf meine Signatur schauen und nicken.

Und nochmal, ich verwende keine solchen Garbage-Collector-Listen (denn das sind die) (@himitsu schau mal in deine Signatur), sondern gebe den Speicher kontrolliert frei. Und falls ich es vergessen habe, dann knallt mit der FastMM das beim Beenden um die Ohren und das ist gut so. Wenn das nicht mehr kommt und ich am Arbeitsspeicherverbrauch nicht die Uhrzeit ablesen kann, erst dann habe ich es richtig gemacht.

SvB 9. Feb 2015 06:51

AW: TObjectList.Free erzeugt AV
 
Gibt es eine Möglichkeit in seinem eigenen Programm mitprotokollieren zu lassen, durch was Speicher verbraucht wird? Am besten wäre die Unit und das einzelne Objekt, die protokolliert wird.

Angenommen ich hab jetzt nicht sauber gearbeitet und während der Laufzeit wird der Speicherverbrauch immer höher, am Ende wirds aber abgeräumt und ich bekomme durch ReportMemoryLeaksOnShutdown := true; keine Meldung.

Wie kann ich diesen Speicherverbrauch ermittelt, damit ich die Objekte entsprechend kontrolliert wieder freigeben kann? (Manchmal sieht man es ja nicht mehr, auch wenn man 100 mal über den Code schaut)
Ich werde ja auch niemals das Programm 2 bis 5 Stunden am Stück testen und damit so arbeiten, wie es ein Benutzer macht. Trotzdem möchte ich sowas gerne herausfinden.

Stevie 9. Feb 2015 07:05

AW: TObjectList.Free erzeugt AV
 
Zitat:

Zitat von SvB (Beitrag 1289247)
Gibt es eine Möglichkeit in seinem eigenen Programm mitprotokollieren zu lassen, durch was Speicher verbraucht wird?

Müsste gehen, indem du
Delphi-Quellcode:
CheckBlocksOnShutdown
aus der FastMM4.pas von außen zugänglich machst.

Alternativ kannst du aber auch AQTime nutzen, das hat nen Memory Profiler.

jaenicke 9. Feb 2015 07:11

AW: TObjectList.Free erzeugt AV
 
Dafür gibt es auch spezielle Tools wie dieses:
http://ddobjects.de/dddebug

Solange du aber die Objekterzeugung und -freigabe nicht sauber umsetzt, wird dir das nicht furchtbar viel helfen fürchte ich.

SvB 9. Feb 2015 07:39

AW: TObjectList.Free erzeugt AV
 
Mit geht es hierbei um folgendes:
Zitat:

Zitat von Sir Rufo (Beitrag 1289232)
Plötzlich melden sich auf einmal die Benutzer, weil nach 2-5h Betrieb der Anwendung ein Speicherfehler kommt: "Arbeitsspeicher voll!"

Mit ReportMemoryLeaksOnShutdown := true; ist das eine, aber ich habe z.B. in meinem Programm ein Formular, das bei einigen Benutzern den ganzen Tag offen ist. Darin ist eine Liste von Daten, die sich in regelmäßigen Abständen im Hintergrund aus eine DB aktualisieren. Wenn ich in dieser ganzen Aktualisierungsgeschichte irgendwo nicht sauber programmiert habe, dann wird der Speicherverbrauch höher und höher. Die Objekte werden erzeugt und an betreffender Stelle nicht freigegeben. Wenn der Owner z.B. das Formular ist, dann wirds ja beim schließen des Fomulars abgeräumt = kein MemoryLeak.

Das möchte ich gerne überprüfen, am besten für einen Tag beim Anwender protokollieren lassen und danach auswerten, damit ich gezielt im Code nachschauen kann.

@Stevie und @jaenicke: Ich schaue mir die Infos an.

PS: wie bekomme ich denn dieses CheckBlocksOnShutdown im Beitrag so angezeigt?


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:38 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