Einzelnen Beitrag anzeigen

Bloodfire

Registriert seit: 17. Jun 2004
38 Beiträge
 
#1

*.Free aufgerufen, aber Speicher bleibt belegt?

  Alt 28. Mai 2005, 14:12
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!?
  Mit Zitat antworten Zitat