ImageList

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Vbxler
Beiträge: 125
Registriert: Sa 25. Mai 2013, 07:43
OS, Lazarus, FPC: Win7_x64 (FPC:4.7.1)
CPU-Target: 32Bit

ImageList

Beitrag von Vbxler »

Hallo Leute,
ich habe eine Frage zur ImageList:

In einer Anwendung verwende ich eine TDataModul um die global verwendeten
Komponenten für Datenbankzugriff und ImageList zu platzieren.
Das funktioniert soweit alles Bestens.
Jetzt habe ich aber versucht in den Compilereinstellungen den Schalter -gh zu
aktivieren um mögliche Memory-Leak zu finden.

Es werden mir sehr viele Error-Meldungen angezeigt:
---------------------------
Error
---------------------------
Heap dump by heaptrc unit of C:\Users\Service.exe
9513 memory blocks allocated : 1861927/1891040
9420 memory blocks freed : 1610476/1639464
93 unfreed memory blocks : 251451
True heap size : 1048576 (128 used in System startup)
True free heap : 789552
Should be : 790920
Call trace for block $00250C20 size 48
$0043D32C
$00556B3E
$0055174E
$005C9AE4
$00428656
$0041C02D
$0041A52A
$00420A5E
Call trace for block $001F64A0 size 92
$0067AF3D
$005C9B8C
$0043E28D
$0043E1B2
$00428644
$0041C02D
$0041A52A
$00420A5E
und so weiter ...

Ich habe herausgefunden, daß das Problem von der Komponente TimageList kommt.
Die Komponente habe ich ebenfalls auf mein TdataModul platziert und dies enthhällt folgenden Coden:

Code: Alles auswählen

 unit uDM;
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, sqldb, mysql55conn, Forms, Controls, UniqueInstance;
 
type
 
  { TuDM }
  TuDM = class(TDataModule)
    ImageList: TImageList;
    mSqlTrans         : TSQLTransaction;
    mSQLConn          : TMySQL55Connection;
    mSqlQuery         : TSQLQuery;
 
    procedure DataModuleCreate(Sender: TObject);
    procedure DataModuleDestroy(Sender: TObject);
 
  private
 
  public
    property SqlConn                : TMySQL55Connection read mSqlConn write mSqlConn;
    property SqlQuery               : TSQLQuery read mSqlQuery write mSqlQuery;
    property SQLTrans               : TSQLTransaction read mSqlTrans write mSqlTrans;
  end;
 
var
  gDM: TuDM;
 
implementation
{$R *.frm}
 
procedure TuDM.DataModuleCreate(Sender: TObject);
begin
 
  ImageList   := TImageList.Create(self);
  mSqlConn    := TMySQL55Connection.Create(self);
  mSqlQuery   := TSQLQuery.Create(self);
  mSqlTrans   := TSQLTransaction.Create(self);
end;
 
procedure TuDM.DataModuleDestroy(Sender: TObject);
begin
  mSqlTrans.Free;
  mSqlQuery.Free;
  mSqlConn.Free;
  ImageList.Free;
end;
end.   


Wenn ich das ImageList entferne habe ich keinen Fehler mehr:
---------------------------
Error
---------------------------
Heap dump by heaptrc unit of C:\Users\Service.exe
8471 memory blocks allocated : 1278836/1305176
8471 memory blocks freed : 1278836/1305176
0 unfreed memory blocks : 0
True heap size : 327680 (128 used in System startup)
True free heap : 327552

Die Procedur DataModuleDestroy wird aufgerufen, das habe ich überprüft.

Könnte mir vielleicht jemand einen Hinweis geben, was ich da falsch mache?


Danke
Vbxler
-------------------------

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1430
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: ImageList

Beitrag von fliegermichl »

Wird evtl bei der Verwendung der Imagelist eine Bitmap erzeugt oder sowas?

Vbxler
Beiträge: 125
Registriert: Sa 25. Mai 2013, 07:43
OS, Lazarus, FPC: Win7_x64 (FPC:4.7.1)
CPU-Target: 32Bit

Re: ImageList

Beitrag von Vbxler »

Ich verwende die Grafiken nur zur Darstellung auf Button (TBCButton) über die Imagelist und Angabe der Item-Nr.
Vbxler
-------------------------

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: ImageList

Beitrag von wp_xyz »

Jetzt wäre gut zu wissen, welche Lazarus und FPC-Version auf welchem Betriebssystem du verwendest.

Wahrscheinlich erzeugt dein Code irgendwie zwischen Create und Destroy das Speicherleck. Bitte stelle ein kleines Projekt zusammen, in dem der Fehler auftritt und das man sich mit dem Debugger anschauen kann. Ich weiß nicht ob man hier schon wieder zip-Dateien hochladen kann. Wenn nicht, schreibe das Projekt irgendwo in die Cloud und poste den Link.

Übrigens: Wenn du einen Nachfahren von TComponent, also auch eine TImageList, mit einem Owner im Create-Aufruf erzeugst, musst du dich selbst nicht mehr um das Freigeben kümmern, das ist genau die Aufgabe des Owners: Er ruft Free für alle Objekte auf, bei denen er als Owner genannt wurde. Insofern ist der OnDestroy-Handler in dem geposteten Code unnötig.

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: ImageList

Beitrag von Mathias »

Wenn ich das ImageList entferne habe ich keinen Fehler mehr:

Man müsste noch etwas Code, sehen, was du sonst noch mit der ImageList machts, ausser Create und Free.

Das Free ist eigentlich gar nicht nötig, da du bei Create, Self mit gibst.

Mit folgendem Mini-Code habe ich kein Leek.

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
begin
  il := TImageList.Create(Self);
  il.Width := 128;
  il.Height := 128;
  il.Add(Image1.Picture.Bitmap, nil);
end;
 
procedure TForm1.FormPaint(Sender: TObject);
begin
  il.Draw(Canvas, 0, 0, 0);
end;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Vbxler
Beiträge: 125
Registriert: Sa 25. Mai 2013, 07:43
OS, Lazarus, FPC: Win7_x64 (FPC:4.7.1)
CPU-Target: 32Bit

Re: ImageList

Beitrag von Vbxler »

Hallo Leute,

danke für eure Hilfe!
Ich habe den Fehler gefunden, er saß einen halben Meter vor dem Monitor.

Ich habe im Datenmodul auch einige Propertys und Methoden für die
globale Verwendung in der Anwendung reingepackt und dann habe ich
beim Start des Programms, beim laden der FormMain nochmals eine
Instanz des DataModule uDM erzeugt:

Code: Alles auswählen

//erstellen der gDM-Instanz
gDM := TuDM.Create(nil);
gDM.DataModuleCreate(self);

Jetzt habe ich eine eigene Klasse für die allgemeinen Propertys angelegt
und erzeuge eine Instanz diese Klasse. Die Methoden DataModuleCreate und
DataModuleDestroy habe ich auch leer gelassen. Beim beenden des Programm
schaue ich nur ob die Verbindung zur Datenbank getrennt werden muss
und zerstöre die beiden Instanzen.

Code: Alles auswählen

//-------------------------------------------------------
// Form wird entladen
//-------------------------------------------------------
procedure TMainForm.FormDestroy(Sender: TObject);
begin
  if (gDM.SQLConn.Connected) then  gDM.SQLConn.Close(True);
 
  gGD.Destroy;
  gDM.Destroy;
  Application.Terminate;
end;   

Es wird angezeigt, dass keine Blöcke verloren gegangen sind:

Code: Alles auswählen

Heap dump by heaptrc unit of c:\_Service.exe
19271 memory blocks allocated : 2278660/2345088
19271 memory blocks freed     : 2278660/2345088
0 unfreed memory blocks : 0
True heap size : 196608 (208 used in System startup)
True free heap : 196400

Danke!
Vbxler
-------------------------

Antworten