![]() |
AW: Fehler beim Programm beenden
Ach so, eins noch. Kann man die vielen Memoryleaks irgendwie den Variablen zuordnen? Weil außer die drei Objekte TOCustomer, TOBuilding, TOSystem sind diese ja nicht eindeutig.
|
AW: Fehler beim Programm beenden
Wie geht man einen Sack voll Memleaks an?
Man beseitigt die bei den bekannten Typen und fängt mit dem an, der die meisten Leaks hat. Diese UnicodeString Leaks sind idR nur Folgefehler davon ;) |
AW: Fehler beim Programm beenden
Hallöle...:P
Zitat:
|
AW: Fehler beim Programm beenden
Warum schlägt keiner vor den vollständigen FastMM4 zu installieren und anhand der viel ausführlicheren Fehlermeldungen das Problem einzukreisen?
Tutorials: ![]() ![]() |
AW: Fehler beim Programm beenden
Vielleicht nicht schön, aber MemoryLeaks beim Beenden sind eh egal. Wenn ich das Haus eh abbrenne, brauch eich die Küche vorher auch nicht feucht wischen. Ich hätte allerdings das Bestreben es ohne MemoryLeaks zu schaffen. Zumindest bei denen für die ich selbst verantwortlich bin.
|
AW: Fehler beim Programm beenden
Wer sagt denn, daß die Leaks nicht schon längst im Lauf des Programms autreten? ODer kann das der FastMM so genau lokalisieren, wann man vergessen hat den Speicher freizugeben ;)?
Sherlock |
AW: Fehler beim Programm beenden
Zu VST und Memory Leaks fallen mir als allererstes immer drei Sachen ein:
|
AW: Fehler beim Programm beenden
Hallo zusammen,
so, die Fehlermeldung beim Programm beenden scheint erstmal weg zu sein. Allerdings sind die MemoryLeaks noch vorhanden. Ich habe jetzt den Tip von "Zacherl" befolgt und das Event "OnFreeNode" entsprechend eingebaut. Irgendwie glaube ich allerdings, dass das ganze nicht ganz sauber Programmiert ist. Ich möchte Euch gerne daher mal versuchen die jeweiligen Teilabschnitte aufzuführen und wäre Euch dankbar, wenn Ihr mir ein kurzes Feedback geben könntet. So, ich versuch das mal Schrittweise darzustellen. Ich erzeuge ein VST mit ungefähr folgendem Aufbau:
Code:
Jeder Kunde kann mehrere Objekte haben. Jedes Objekt kann mehrere Systeme haben und Jedes System hat mehrere Menüpunkte.
+Hauptknoden (Zeigt den Datenbankpfad an)
+Kunde_1 +Objekt_1 +System_1 +Menü_1 +Menü_2 +Menü_3 +System_2 +Menü_1 +Menü_2 +Menü_3 +Objekt_2 +System_1 +Menü_1 +Menü_2 +Menü_3 +Kunde_2 +Objekt_1 +System_1 +Menü_1 +Menü_2 +Menü_3 +Objekt_2 +System_1 +Menü_1 +Menü_2 +Menü_3 Erzeugen tue ich das ganze dann in etwa so... Ich habe je ein Objekt für die Kundendaten, Objektdaten und Systemdaten. Diese sind jeweils ähnlich und wie folgt aufgebaut...
Delphi-Quellcode:
ähnlich sieht das Objekt für "Objekte" und "System" aus.
unit Customers;
interface uses Buildings; { TObject für die Kundendaten } type TOCustomers = class(TObject) private FID : integer; //ID FESID : integer; //ESID FName : string; //Name des Kunden FOrt : string; //Ort des Kunden FStraße : string; //Straße des Kunden FAnsprechpartnerId : integer; //Ansprechpartnernummer FAnsprechpartner : string; //Ansprechpartner FAnsPosition : string; //Position/Stellung FEMail : string; //EMail des Ansprechpartners FTel1 : string; //Telefonnummer 1 des Ansprechpartners FTel2 : string; //Telefonnummer 2 des Ansprechpartners FFax : string; //Faxnummer des Ansprechpartners FBemerkung : string; //Kunden Zusatzinformation public property Kunden_Kundennummer : integer read FID write FID; property Kunden_ESKundennummer : integer read FESID write FESID; property Kunden_Kundenname : string read FName write FName; property Kunden_Ort : string read FOrt write FOrt; property Kunden_Straße : string read FStraße write FStraße; property Kunden_Bemerkung : string read FBemerkung write FBemerkung; property Ansprechpartner_Id : integer read FAnsprechpartnerId write FAnsprechpartnerId; property Ansprechpartner_Name : string read FAnsprechpartner write FAnsprechpartner; property Ansprechpartner_Position : string read FAnsPosition write FAnsPosition; property Ansprechpartner_EMail : string read FEMail write FEMail; property Ansprechpartner_Telefon1 : string read FTel1 write FTel1; property Ansprechpartner_Telefon2 : string read FTel2 write FTel2; property Ansprechpartner_Fax : string read FFax write FFax; end; implementation end. In meinem Hauptformular nutze ich die Objekte wie folgt:
Delphi-Quellcode:
...
interface uses ... type PCustomersData = ^TCustomersData; TCustomersData = record FCustomer_Object : TObject; end; type PBuildingsData = ^TBuildingsData; TBuildingsData = record FBuilding_Object : TObject; end; type PSystemsData = ^TSystemsData; TSystemsData = record FSystem_Object : TObject; end; ... private { Private-Deklarationen } var .... //Diese Globalen Variablen nutze ich für das LoadData TMyKunden_Daten : TOCustomers; TMyObjekt_Daten : TOBuilding; TMySystem_Daten : TOSystems; ... public { Public-Deklarationen } procedure LoadData; var fMyForm: TfMyForm; implementation //Das hinzufügen der Daten mache ich dann über folgende Methode: procedure TfMyForm.LoadData; var I,J,K : Integer; CustomerNode, BuildingNode, SystemNode : PVirtualNode; begin try vstKunden.BeginUpdate; vstKunden.Clear; CustomerNode := vstKunden.AddChild(nil); vstKunden.InvalidateNode (CustomerNode); vstKunden.NodeDataSize:=SizeOf(TCustomersData); {Hier glaube ich liegt das erste Problem. Ich setze NodeDataSize auf TCustomersData. Was aber ist mit TBuildingData und TSystemData? Benötige ich die nicht, weil es nur um den ersten Node geht?} //Jetzt lade ich die Kundendaten aus der DB und lasse das ganze durch eine for-Schleife laufen TMyKunden_Daten := TOCustomers.Create; with TMyKunden_Daten do begin //Daten zufügen //Inerhalb der Schleife folgen dann die tieferen Datenpunkte BuildingNode := AddVSTCustomer(vstKunden,CustomerNode,TMyKunden_Daten); //Objektedaten laden aus Objektdatenbank //Systemdaten //Menüpunkte end; vstKunden.EndUpdate; ExpandedRootNodes(vstKunden); vstKunden.SortTree(0, sdAscending, True); finally //Queries schließen etc. end;
Delphi-Quellcode:
Dann weiße ich über "OnGetText" die Bezeichnung zu und über "OnGetImageIndex" noch ein paar Icons
//Hier die Funktion AddVSTCustomer, die weiteren Add-Funktionen sind ähnlich
function TfReportClient.AddVSTCustomer(AVST: TCustomVirtualStringTree; ANode: PVirtualNode; AObject: TObject): PVirtualNode; var Data : PCustomersData; begin Result := AVST.AddChild(ANode); AVST.ValidateNode(Result,False); Data := AVST.GetNodeData(Result); Data^.FCustomer_Object := AObject; end; Das "OnFreeNode" sieht aktuell wie folgt aus...
Delphi-Quellcode:
Die Globalen Var. gebe ich im FormDestroy wieder frei...
procedure TfReportClient.vstKundenFreeNode(Sender: TBaseVirtualTree;
Node: PVirtualNode); var Kunden_Daten : PCustomersData; Objekt_Daten : PBuildingsData; System_Daten : PSystemsData; begin case vstKunden.GetNodeLevel(Node) of 0: begin Kunden_Daten := Sender.GetNodeData(Node); Finalize (Kunden_Daten^); end; 1: begin Objekt_Daten := Sender.GetNodeData(Node); Finalize (Objekt_Daten^); end; 2: begin System_Daten := Sender.GetNodeData(Node); Finalize (System_Daten^); end; end; end;
Delphi-Quellcode:
Ich vermute, das einige von Euch jetzt schon die Hände über dem Kopf zusammengeschlagen haben :oops:
procedure TfReportClient.FormDestroy(Sender: TObject);
begin TMyKunden_Daten.Free; TMyObjekt_Daten.Free; TMySystem_Daten.Free; end; Aber vieleicht könnt Ihr mir ja mal ein paar Tips geben. Danke schon mal und Gruß Jens |
AW: Fehler beim Programm beenden
Zitat:
Beispiel: Wenn du 10 Kunden erzeugst
Delphi-Quellcode:
, gibst du im FormDestroy nur Nummer 9 frei.
TMyKunden_Daten := TOCustomers.Create;
Die Kunden 0 bis 8 hängen noch im Speicher rum und das sind deine Speicherlecks. Verwalte doch diese Instanzen von Kunden, Systemen und Gebäuden in seperaten Objektlisten. Bei Freigabe der Objektlisten werden dann auch die darin gespeicherten Instanzen freigeben. Beispiel:
Delphi-Quellcode:
var
I, J, K: Integer; CustomerNode, BuildingNode, SystemNode: PVirtualNode; LCustomer: TOCustomers; begin VstKunden.BeginUpdate; try VstKunden.Clear; CustomerNode := VstKunden.AddChild(nil); VstKunden.InvalidateNode(CustomerNode); VstKunden.NodeDataSize := SizeOf(TCustomersData); { Hier glaube ich liegt das erste Problem. Ich setze NodeDataSize auf TCustomersData. Was aber ist mit TBuildingData und TSystemData? Benötige ich die nicht, weil es nur um den ersten Node geht? } FCustomers := TObjectList.Create; // Jetzt lade ich die Kundendaten aus der DB und lasse das ganze durch eine for-Schleife laufen for I := 0 to 10 do begin LCustomer := TOCustomers.Create; FCustomers.Add(LCustomer); LCustomer.Kunden_Kundenname := 'Hallo'; LCustomer.Ansprechpartner_Position := 'Hallo'; LCustomer.Ansprechpartner_Telefon1 := 'Hallo'; // Inerhalb der Schleife folgen dann die tieferen Datenpunkte BuildingNode := AddVSTCustomer(VstKunden, CustomerNode, LCustomer); // Objektedaten laden aus Objektdatenbank // Systemdaten // Menüpunkte end; // ExpandedRootNodes(VstKunden); VstKunden.SortTree(0, SdAscending, True); finally VstKunden.EndUpdate; end; end; |
AW: Fehler beim Programm beenden
Ergänzung:
Das OnFreeNode des VST brauchst du dann nicht mehr, da du die Freigabe selbst machst. Ist doch auch irgendwie logischer: Du erzeugst die Objekte, übergibst sie dem VST zur Anzeige, und zerstörst sie selbst wieder. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:05 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-2025 by Thomas Breitkreuz