Текущий архив: 2008.05.18;
Скачать: CL | DM;
ВнизПочемуто переменная сама меняется :( Найти похожие ветки
← →
andreil © (2008-04-16 10:20) [0]Процедура, в которой собственно идет ошибка:
function TGcf.ValidateItemInternal(const Item: ulong): TValidation;
var
_Checksum: ulong;
buf: array of byte;
bufSize: ulong;
ReadSize, ReadingSize, RSize, ReadPos, n, CheckNum, CheckOffs, i: ulong;
begin
result:=HL_VALIDATES_OK;
bufSize:=lpDirectoryEntries[Item].ItemSize;
SetLength(buf, HL_GCF_CHECKSUM_LENGTH);
Self.BuildFileInfo(Item, @Self.SectorsTable);
i:=0;
ReadingSize:=BUFFER_SIZE;
RSize:=0;
CheckNum:=0;
CheckOffs:=0;
repeat
if Exit_ then
Exit;
ReadSize:=0;
for n:=i to length(SectorsTable[Item])-1 do
begin
inc(ReadSize, BUFFER_SIZE);
ReadingSize:=BUFFER_SIZE;
ReadPos:=pDataBlockHeader.FirstSectorOffset+
(pDataBlockHeader.PhysicalSectorSize*SectorsTable[Item][n]);
if ReadSize+RSize>=lpDirectoryEntries[Item].ItemSize then
begin
ReadingSize:=lpDirectoryEntries[Item].ItemSize-RSize-ReadSize+BUFFER_SIZE;
ReadSize:=ReadSize-BUFFER_SIZE+ReadingSize;
end;
GcfStream.Seek(ReadPos, spBegin);
GcfStream.Read(buf[CheckNum*BUFFER_SIZE], ReadingSize);
inc(CheckNum);
if CheckNum=4 then
begin
CheckNum:=0;
_Checksum:=Checksum(@buf[0], HL_GCF_CHECKSUM_LENGTH);
if _checksum<>Self.lpChecksumEntries[lpChecksumMapEntries[Self.lpDirectoryEntries[I tem].ChecksumIndex].FirstChecksumIndex+CheckOffs].Checksum then
begin
result:=HL_VALIDATES_INCOMPLETE;
Exit;
end;
inc(CheckOffs);
end;
if (ReadSize=BUFFER_SIZE*64) or (n=(length(SectorsTable[Item])-1)) then
begin
break;
end;
end;
i:=n+1;
inc(RSize, ReadSize);
until i>=length(SectorsTable[Item]);
end;
Проблема заключается в том, что при чтении одного из потока переменная CheckNum произвольно меняется :(
В чем может быть проблема?
Да, меняется переменная не при первом чтении, а где-то после 5-7.
← →
Сергей М. © (2008-04-16 10:24) [1]Что показывает отладчик ?
← →
Семеныч (2008-04-16 10:26) [2]Можно поставить точку останова на изменение переменной.
← →
palva © (2008-04-16 10:44) [3]Может переполнение буфера? Неправильно вычисляем размер чтения.
← →
andreil © (2008-04-16 11:10) [4]Отладчик показывает, что до чтения зачение было менее 4, а после чтения зашкалило за 100000.
Переполнения буфера нету, тк если убрать все, что относится к вычислению КС, те блокinc(CheckNum);
if CheckNum=4 then
begin
CheckNum:=0;
_Checksum:=Checksum(@buf[0], HL_GCF_CHECKSUM_LENGTH);
if _checksum<>Self.lpChecksumEntries[lpChecksumMapEntries[Self.lpDirectoryEntries[I tem].ChecksumIndex].FirstChecksumIndex+CheckOffs].Checksum then
begin
result:=HL_VALIDATES_INCOMPLETE;
Exit;
end;
inc(CheckOffs);
end;
то никаких ошибок нету, да и читает правильно...
← →
Сергей М. © (2008-04-16 11:25) [5]Значит проблема здесь:
> GcfStream.Read(buf[CheckNum*BUFFER_SIZE], ReadingSize);
Контролируй выход за пределы буфера.
← →
andreil © (2008-04-16 11:30) [6]Сделал так:
1) убрал расчет КС из самого чтения.
2) вынес его в конец процедуры.
В итоге файл читается нормально, что доказал сброс дампа на диск с его сверкой (1 к 1 с оригиналом). Значит, чтение нормально.
Расчет КС получился таков:for i:=0 to lpChecksumMapEntries[Self.lpDirectoryEntries[Item].ChecksumIndex].ChecksumCount-1 do
begin
_Checksum:=Checksum(@buf[i*HL_GCF_CHECKSUM_LENGTH], HL_GCF_CHECKSUM_LENGTH);
if _checksum<>Self.lpChecksumEntries[lpChecksumMapEntries[Self.lpDirectoryEntries[I tem].ChecksumIndex].FirstChecksumIndex+i].Checksum then
begin
result:=HL_VALIDATES_INCOMPLETE;
Exit;
end;
end;
В итоге, при одном из обращний к буфферу выскакивает ошибка. Причем номер этого обращения колеблется (первый раз было 3, сейчас 1).
Что за фигня?
ЗЫ: Сам расчет КС находится в С++ ДЛЛке, откуда и вызавается. Все, что имеет отношение к этому вызову, расписано правильно, тк иначе при первом же обращении вылазилабы ошибка.
← →
Сергей М. © (2008-04-16 11:38) [7]
> при одном из обращний к буфферу выскакивает ошибка
Какая конкретно - это военная тайна ?
← →
andreil © (2008-04-16 11:53) [8]Все, уже не выскакивает :) Перевел эту ДЛЛку на дельфи. благо, там только две функции (Adler32 & CRC32). Помощь больше не нужна ;)
← →
Сергей М. © (2008-04-16 11:56) [9]Полагаю, dll здесь была ни причем.
← →
han_malign © (2008-04-16 13:24) [10]
> Полагаю, dll здесь была ни причем.
- ну почему же - если в DLL Checksum() объявлена как stdcall, а в программе как cdecl, то на 4-м проходе(if CheckNum=4) после вызова Checksum указатель стека сдвигается на лишних 8-мь байт, и в аккурат на 5-ом проходе при GcfStream.Seek и GcfStream.Read как раз на место CheckNum и попадает адрес возврата...
> Все, что имеет отношение к этому вызову, расписано правильно,
> тк иначе при первом же обращении вылазилабы ошибка.
- ну-ну, стек и не такое стерпит... до поры - до времени...
← →
Сергей М. © (2008-04-16 13:27) [11]
> если в DLL Checksum() объявлена как stdcall, а в программе
> как cdecl
То это точно не проблема dll, это проблема автора, проставившего соглашение от балды)
Страницы: 1 вся ветка
Текущий архив: 2008.05.18;
Скачать: CL | DM;
Память: 0.48 MB
Время: 0.045 c