Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi *.Free aufgerufen, aber Speicher bleibt belegt? (https://www.delphipraxis.net/46626-%2A-free-aufgerufen-aber-speicher-bleibt-belegt.html)

Bloodfire 28. Mai 2005 13:12


*.Free aufgerufen, aber Speicher bleibt belegt?
 
Hi!

Zum besseren Verständis kruz die Vorgeschichte:
Das Programm soll ein Netzwerkschach werden, das aus einer Hauptform mit Userliste besteht, über die je Benutzer ein (aber maximal 5 insgesamt) Schachbrett aufgerufen wird.

Die Klasse des Schachbrettes ist ein TObject, welche eine Form beinhaltet und in etwa so aufgebaut ist:

Delphi-Quellcode:
  TChessBoard = class(TObject)
    ChessboardForm: TForm;
  private
    (...)
  public
    FormClosed: Boolean;

    constructor Create;
    destructor Destroy;override;
    (...)
Im Konstruktor wird nur die Form mit dem Owner 'nil' erzeugt und demnach auch in Destroy wieder freigegeben. Der Owner aller anderen kreierten Objekte ist die Form. (so müsste ich mich ja eigentlich nicht mehr um deren Löschung kümmern, oder?)

Delphi-Quellcode:
constructor TChessBoard.Create;
var
 i: Integer;
 TempOwner: TComponent;
begin
   //Formular
   ChessboardForm:=TForm.Create(nil);
   TempOwner:=ChessboardForm;

   //Menü
   MainMenu:=TMainMenu.Create(TempOwner);

   for i:=0 to MenuItemCount do
     MenuItem[i]:=TMenuItem.Create(MainMenu);

   //BoardPanel & Board
   BoardPanel:=TPanel.Create(TempOwner);
   Board:=TImage.Create(TempOwner);
   (...)
end;


destructor TChessBoard.Destroy;
begin
  ChessboardForm.Free;
  inherited;
end;
Da ich nun bei OnFormClose nicht die Klasse TChessboard befreien kann, setze ich die Variable FormClosed einfach auf True. Der Aufruf der einzelnen Schachbretter im Hauptprogramm sieht dann folgendermaßen aus:

Delphi-Quellcode:
procedure TMainAppSingle.OpenChess(FName: String; FLeft, FTop, FWidth,
  FHeight: Integer; FPathFigures, FExtFigures, FPathGraphics, FExtGraphics,
  FPathFiles: String; FBoardIndex: Integer);
var
  i: Integer;
  AMsg: String;
begin
   //Überprüfen, ob laufendes Chessboard schon geschlossen wurde
   for i:=1 to MaxChess do
     if not(ChessFree[i]) then
       if (ChessBoard[i].FormClosed) then
         begin
            ChessBoard[i].Free;
            ChessFree[i]:=True;
            dec(RunningChess);
         end;

   //Überprüfen, ob Schach mit diesem User schon läuft
   for i:=1 to MaxChess do
     if not(ChessFree[i]) then
       if ChessBoard[i].ChessboardForm.Caption=FName then
         begin
            ChessBoard[i].ChessboardForm.BringToFront;
            exit;
         end;

   //Überprüfen, ob Maximalanzahl an Schachbretterb initialisiert wurden
   if (RunningChess>=MaxChess) then
     begin
        AMsg:=SysCommands.ReadCaption('MainApp','MaxChess')+
          ' ('+IntToStr(MaxChess)+')';
        MessageDlg(AMsg,mtInformation,[mbOk],0);
        exit;
     end;


   //Neues Spiel initialisieren:

   inc(RunningChess);

   i:=1;
   while (not(ChessFree[i]))
     do inc(i);

   ChessFree[i]:=False;
   ChessBoard[i]:=TChessBoard.Create;
   ChessBoard[i].Init(nil,FName,FLeft,FTop,FWidth,FHeight,
     FPathFigures,FExtFigures,FPathGraphics,FExtGraphics,FPathFiles,
     FBoardIndex);
end;
(zur Info: die Parameter für die Netzwerkübertragung sind noch ausständig)

Essentielles Kurz zusammengefasst:
Ich überprüfe, ob eines der vormals geöffneten Schachfenster geschlossen wurde (die Klasse aber noch existiert) und befreie diese dann vom Speicher, was eigentlich bedeuten müsste:

Wenn ich zum Beispiel 2 Schachbretter aufmache und eines davon wieder schließe liegt der Speicherbedarf immernoch gleich. Wenn ich jedoch nun ein neues öffne, sollte der gleichbleiben, da ja die im untergrund noch existierende Klasse gelöscht, und die neue initielisiert wird, aber laut Taskmanager, nimmt der Bedarf an Speicher nur zu und ab etwa dem 10. Spielaufruf wird das auch an der Performance sichtbar.

Wo liegt hier der Fehler? Vergesse ich etwas zu befreien? Oder funktioniert das grundsätzlich anders!?

Phistev 28. Mai 2005 13:28

Re: *.Free aufgerufen, aber Speicher bleibt belegt?
 
Erstell mal ein eigenes Form (statt TForm) mit Hilfe des Formulardesigners. Evtl. muss intern eine Variable anders gesetzt werden. Alternativ gib die Komponenten selber frei (mittels TForm.Controls).

Christian Seehase 28. Mai 2005 13:33

Re: *.Free aufgerufen, aber Speicher bleibt belegt?
 
Moin Bloodfire,

prüfe Dein Programm am besten mal mit MemProof, bzw. MemCheck.

Aussderdem könntest Du Dein Hauptprogramm vermutlichen vereinfachen, wenn Du Dir noch eine Klasse für die Liste der Formulare erstellst, und dort diese die Verwaltung übernimmt (Stichwort: TObjectList).


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