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!?