1-2週間前に「ブロックヘッダーが破損しました」と「ブロックが解放された後に変更されました」というエラーが表示されました。ダイナミックアレイ用メモリの割り当て - ブロックヘッダーが破損しています(FastMM4)
誰かが、FullDebugModeScanMemoryPoolBeforeEveryOperationをtrueに設定することについての良いアドバイス(感謝のアレクサンダー)を与えてくれました。そして、最後に、エラーの真の位置がどこにあるかについていくつかの兆候があります。
エラーログは、TScObjオブジェクトを指します。私はこの1つに非常に似た2番目のオブジェクトを持っています。私が使用すると、エラーは表示されません。したがって、これは何らかの形でエラーがこの特定のオブジェクト(TScObj)にあることを確認します。
ログは、このようなものです:
FastMM has detected an error during a free block scan operation.
FastMM detected that a block has been modified after being freed.
Modified byte offsets (and lengths): 15656(1)
The previous block size was: 15672
This block was previously allocated by thread 0xC88, and the stack trace (return addresses) at the time was:
402EC9 [System][@ReallocMem]
40666C [System][DynArraySetLength]
40A17D [FastMM4][UpdateHeaderAndFooterCheckSums]
40674E [System][@DynArraySetLength]
4CE329 [ReadSC.pas][ReadSC][TScObj.ReadData][239]
4CDD0C [ReadSC.pas][ReadSC][TScObj.LoadFromFile][168]
4D013E [SmplCubImport.pas][SmplCubImport][TCubImport.ImportSample][164]
40461A [System][@AfterConstruction]
4DC151 [UnitAsmJob.pas][UnitAsmJob][TAsmJob.LoadSample][960]
The allocation number was: 78709
The block was previously freed by thread 0xC88, and the stack trace (return addresses) at the time was:
402E6F [System][@FreeMem]
4068A8 [System][@DynArrayClear]
405DF9 [System][@FinalizeArray]
4CE9F9 [ReadSC.pas][ReadSC][TScObj.ReadData][298]
4CDD0C [ReadSC.pas][ReadSC][TScObj.LoadFromFile][168]
4D013E [SmplCubImport.pas][SmplCubImport][TCubImport.ImportSample][164]
40461A [System][@AfterConstruction]
4DC151 [UnitAsmJob.pas][UnitAsmJob][TAsmJob.LoadSample][960]
の事は私が不当にメモリを割り当てることができ、私のコード内の任意の場所が表示されないということです。
type
TWordTrace = array of Word;
TDiskTrc = array of Smallint;
var Tracea,Tracec: TWordTrace;
procedure TScObj.ReadData;
Var i: Integer;
DiskTrc1: TDiskTrc;
DiskTrc2: TDiskTrc;
DiskTrc3: TDiskTrc;
DiskTrc4: TDiskTrc;
begin
SetLength(DiskTrc1, H.NrOfSamples+1);
SetLength(DiskTrc2, H.NrOfSamples+1);
SetLength(DiskTrc3, H.NrOfSamples+1);
SetLength(DiskTrc4, H.NrOfSamples+1); <------ log shows error here. <- on DynArraySetLength
FStream.Seek(H.SOffset, soFromBeginning);
if H.SampleSize = 1 then
begin
for i:= 1 TO H.NrOfSamples DO
FStream.Read(DiskTrc1[i], 1);
Unpack(DiskTrc1);
for i:= 1 TO H.NrOfSamples DO
FStream.Read(DiskTrc2[i], 1);
Unpack(DiskTrc2);
etc...
end
else
begin
for i:= 1 TO H.NrOfSamples DO
begin
FStream.Read(DiskTrc1[i], 2);
DiskTrc1[i]:= Swap(DiskTrc1[i]);
end;
Unpack(DiskTrc1);
for i:= 1 TO H.NrOfSamples DO
begin
FStream.Read(DiskTrc2[i], 2);
DiskTrc2[i]:= Swap(DiskTrc2[i]);
end;
Unpack(DiskTrc2);
etc...
end;
SetLength(Tracea, H.NrOfSamples+1);
SetLength(Tracec, H.NrOfSamples+1);
SetLength(Traceg, H.NrOfSamples+1);
SetLength(Tracet, H.NrOfSamples+1); <------ log shows error here. <- on FinalizeArray
for i:=1 to H.NrOfSamples DO
begin
if DiskTrc1[i]< 0
then Tracea[i]:= 0
else Tracea[i]:= DiskTrc1[i];
if DiskTrc2[i]< 0
then Tracec[i]:= 0
else Tracec[i]:= DiskTrc2[i];
etc...
end;
end;
procedure TScObj.Unpack(VAR DiskTrc: TDiskTrc);
var i: integer;
Prev: Integer;
Recover: Integer;
begin
Prev:= 0;
for i:= 1 to H.NrOfSamples do
begin
Recover := DiskTrc[i] + Prev;
if (Recover> 32767) OR (Recover< -32768)
then Recover:= 0;
DiskTrc[i]:= Recover;
Prev:= DiskTrc[i];
end;
Prev:= 0;
for i:= 1 to H.NrOfSamples do
begin
Recover := DiskTrc[i] + Prev;
if (Recover> 32767) OR (Recover< -32768)
then Recover:= 0;
DiskTrc[i]:= Recover;
Prev:= DiskTrc[i];
end;
end;
その後「ロードディスクから」手順の間に、一時的ローダオブジェクト(SC)からの情報は、このように、より多くの「決定的な」オブジェクトに転送され:
TSam = class
etc...
for i:= 1 to NrOfSamples DO
begin
CMX[i].Tracea:= SC.Tracea[i];
CMX[i].Tracec:= SC.Tracec[i];
etc...
end;
編集2: 非常に特定の(2つの)ファイルセットを開いて/ロードしようとすると、バグが表示されます。他のすべてのファイルについては、バグは表示されません。
TDiskTrcの宣言は何ですか?要素のサイズが十分に大きい(少なくとも2)か、多分、各要素にあまりにも多くの(2)バイトを読み込もうとメモリを上書きしていますか?また、スワップとアンパックは何をするのですか? –
こんにちはTOndrej。 Unpackを表示するために投稿を更新しました。 TDiskTrcは、これらの2バイトを保持できます。スワップはDelphi.systemで定義されています。 – Ampere
ところで、古いものとその逆のためのこの質問へのリンクを追加するとよいでしょう。 – Alex