У меня была тема 1-2 недели назад о «повреждении заголовка блока» и «Блокировка была изменена после освобождения».Выделение памяти для динамического массива - заголовок блока был поврежден (FastMM4)
Кто-то дал мне хороший совет (спасибо Александру) о том, как установить FullDebugModeScanMemoryPoolBeforeEveryOperation в true и, наконец, у меня есть некоторые указания о том, где находится ИСТИННОЕ местоположение ошибки.
Журнал ошибок указывает на объект TScObj. У меня есть второй объект, очень похожий на этот, и когда я его использую, ошибка не появляется. Итак, это как-то подтверждает, что ошибка находится в этом конкретном объекте (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: Ошибка появляется только при попытке открыть/загрузить очень специфический набор (двух) файлов. Для всех других файлов ошибка не отображается.
Что такое объявление TDiskTrc? Является ли размер элемента достаточно большим (не менее 2) или вы, возможно, перезаписываете память, пытаясь прочитать слишком много (2) байтов в каждый элемент? Кроме того, что делают Swap и Unpack? –
Hi TOndrej. Я обновил свое сообщение, чтобы показать Распаковать. TDiskTrc может содержать эти два байта. Swap определяется в Delphi.system. – Ampere
BTW, было бы неплохо добавить ссылку на этот вопрос для старого и наоборот. – Alex