![]() |
FastMM4 - Verbuggt?
Hallo erstmal. :)
Das ist meine erste Frage in diesem Forum, also bitte nicht gleich lynchen wenn ich in der falschen Area gepostet habe (dies scheint die richtige zu sein für diese Frage). :) Also und zwar möchte ich eine Klasse schreiben, die ein Spielfeld speichert. Diese soll jeweils einen Wert pro Feld speichern. Dies möchte ich direkt im Speicher realisieren und nicht als verkettete Liste. Da es sich um eine Schulaufgabe handelt und wir leider ein paar dämliche restriktionen haben, dürfen wir dynamische Arrays nicht benutzen. Nun ja, soweit läuft die Klasse auch. Die größe lässt sich mit der ChangeSize Prozedur problemlos verändern. Allerdings macht die AddRow Prozedur Probleme, die eine neue Zeile an beliebiger Stelle einfügen soll. Wenn ich diese Prozedur ausführe, gibt mir FastMM (und Delphi) eine Fehlermeldung bei dem Befehl FreeMem(Data); im Destruktor. FastMM sagt "The block footer has been corrupted." und Delphi wirft die Exception EInvalidPointer mit der Nachricht 'Ungültige Zeigeroperation.'. Delphi wirft allerdings keine Exception wenn ich FastMM nicht mit in das Programm kompiliere. Nun frage ich mich ob dies ein Problem mit FastMM ist (da ohne keine Exception auftritt), oder ob wirklich was mit dem Code nicht stimmt. Hier ist der gesamte Code der Unit:
Code:
Kann mir jemand vielleicht helfen? :)
unit UMemMap;
interface uses SysUtils, Graphics; type PFType = ^TFType; TFType = ( ftFree, ftWater, ftUndestroyable, ftDestroyable ); TMapData = record Name : String; Fieldsize : Word; BgColor : TColor; Images : array [ftWater..ftDestroyable] of String; end; TMemMap = class private Data : Pointer; Rows, Cols : Word; public destructor Destroy; override; procedure AddRow(PrevRow : Word); procedure ChangeSize(NewRows, NewCols : Word); procedure UpdateField(Row, Col : Word; FType : TFType); procedure Echo; end; implementation destructor TMemMap.Destroy; begin FreeMem(Data); inherited end; procedure TMemMap.AddRow(PrevRow : Word); var NewData : Pointer; Row, Col : Integer; begin GetMem(NewData, (Rows + 1) * Cols * SizeOf(TFType)); for Row := 0 to PrevRow - 1 do for Col := 0 to Cols do PFType(Integer(NewData) + (Row * Cols + Col) * SizeOf(TFType))^ := PFType(Integer(Data) + (Row * Cols + Col) * SizeOf(TFType))^; for Col := 0 to Cols do PFType(Integer(NewData) + (PrevRow * Cols + Col) * SizeOf(TFType))^ := ftFree; for Row := PrevRow + 1 to Rows do for Col := 0 to Cols do PFType(Integer(NewData) + (Row * Cols + Col) * SizeOf(TFType))^ := PFType(Integer(Data) + ((Row - 1) * Cols + Col) * SizeOf(TFType))^; FreeMem(Data); Inc(Rows); Data := NewData end; procedure TMemMap.ChangeSize(NewRows, NewCols : Word); var NewData : Pointer; Row, Col : Integer; begin if (NewRows = 0) or (NewCols = 0) then NewData := nil else begin GetMem(NewData, NewRows * NewCols * SizeOf(TFType)); for Row := 0 to NewRows - 1 do begin for Col := 0 to NewCols - 1 do if (Col > Cols - 1) or (Row > Rows - 1) then PFType(Integer(NewData) + (Row * NewCols + Col) * SizeOf(TFType))^ := ftFree else PFType(Integer(NewData) + (Row * NewCols + Col) * SizeOf(TFType))^ := PFType(Integer(data) + (Row * Cols + Col) * SizeOf(TFtype))^ end end; FreeMem(Data); Rows := NewRows; Cols := NewCols; Data := NewData end; procedure TMemMap.UpdateField(Row, Col : Word; FType : TFType); begin PFType(Integer(Data) + ((Row - 1) * Cols + (Col - 1)) * SizeOf(TFType))^ := FType end; procedure TMemMap.Echo; var Row, Col : Integer; begin writeln('Ausagbe: ', Cols, 'x', Rows); for Row := 0 to Rows - 1 do begin for Col := 0 to Cols - 1 do write(Word(PFType(Integer(Data) + (Row * Cols + Col) * SizeOf(TFType))^), ' '); writeln end; writeln end; end. Sollte es wirklich an FastMM liegen: Gibt es noch gute Alternativen um Speicherlecks festzustellen? Mit freundlichen Grüßen Snaeng Edit: Es handelt sich übrigens um die Version 4.90 von FastMM. |
Re: FastMM4 - Verbuggt?
FastMM4 wirft mit Absicht eine Exception, damit das fehlerhafte Programm nicht weiterläuft bzw. Du an die Stelle findest, an der das Problem auftritt.
In deinen Records sollte kein dynamischer String deklariert werden, sondern immer ein Statischer: Ändere mal die Deklaration des Records delphi] TMapData = record Name : String; Fieldsize : Word; BgColor : TColor; Images : array [ftWater..ftDestroyable] of String; // <<<< Möööööppp end; [/delphi] Frage: Wieso verwendest Du nicht einfach dynammische Arrays? |
Re: FastMM4 - Verbuggt?
Hallo.
Danke erstmal für deine Antwort. :) Ich habe vergessen den Record aus dem Code zu entfernen. Wie man sehen kann ist er noch garnicht enthalten. Ich benutze dynamische Arrays nicht, da sie nach der Aufgabenstellung verboten sind. Warum auch immer... Und da ich ebenfalls die Compiler-Direktive HugeStrings abgeschaltet habe, hat String auch keine dynamische Größe. :) Das Problem ist ja: Warum wirft FastMM4 eine Exception? An FreeMem(Data); ist doch nichts falsch?! Auch wenn ich die Größe jeweils angebe kommt diese Fehlermeldung. Snaeng |
Re: FastMM4 - Verbuggt?
FastMM erzeugt im Debugmodus um jeden Speicherblock Schutzblöcke. Wird der Speicherblock frei gegeben wird dieser Block auf Unversehrtheit überprüft und wenn diese nicht der Fall ist eine Fehlermeldung erzeugt um Aufzuzeigen das dein Programm über den reservierten Block hinaus geschrieben hat. Das ohne FastMM das nicht auftritt heißt nur das der alte Memorymanger von alten Delphi-Versionen einfach sowas nicht erkannt hat und dein Progamm stattdessen irgendwan mal irgendwas komisches macht.
|
Re: FastMM4 - Verbuggt?
Aber wo in meinem Code tritt denn dieser Fehler auf? Soweit ich das sehe ist doch alles in Ordnung, ich überschreibe keinen unreservierten Speicher und ich gebe den Speicher immer frei.
Code:
Damit teste ich die Klasse übrigens. Und eben bei List.Free - wenn der Destruktor aufgerufen wird - tritt diese Fehlermeldung auf. Sie tritt allerdings nicht auf, wenn ich AddRow nicht aufrufe - Egal wie oft ich ChangeSize aufrufe. Also mit ChangeSize sollte alles in Ordnung sein.
List := TMemMap.Create;
List.ChangeSize(2, 2); List.AddRow(1); List.Echo; List.Free Snaeng |
Re: FastMM4 - Verbuggt?
Ich hab den Quelltext jetzt gerade mal überflogen und mir ist da was aufgefallen:
Delphi-Quellcode:
und hier
procedure TMemMap.ChangeSize(NewRows, NewCols : Word);
begin begin for Row := 0 to NewRows - 1 do begin for Col := 0 to NewCols - 1 do // <-- hier gehst du bis NewCols - 1 end end; end;
Delphi-Quellcode:
Ich hab jetzt nicht genau genug hingeschaut, jedoch das ist schon auffällig.
procedure TMemMap.AddRow(PrevRow : Word);
begin for Row := 0 to PrevRow - 1 do for Col := 0 to Cols do // <-- hier gehst du bis Cols und nicht Cols-1 end; |
Re: FastMM4 - Verbuggt?
Genau das ist mir jetzt gerade auch aufgefallen! :)
Ständig angeschaut und überprüft, aber genau das immer übersehen... Danke danke! :) Endlich Problem gelöst. Lag also doch nicht an FastMM4 *G*. Happy Snaeng |
Re: FastMM4 - Verbuggt?
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:09 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