Форум: "Начинающим";
Текущий архив: 2009.01.11;
Скачать: [xml.tar.bz2];
ВнизAccess violation и MapViewOfFile Найти похожие ветки
← →
man Yury (2008-11-29 12:05) [0]Доброе утро/день All.
Кто может обьяснить почему возникает ошибка [B]Access Violaion[/B] и направить на путь истинный в следующем коде (при открытии файла размером кратного 4096 байт на OS Windows2003 SP1 размер кластера 4096 байт)
hFile:=FileOpen(FDirectoryFromSAA+FileForProcess.Name,fmOpenReadWrite);
if hFile=INVALID_HANDLE_VALUE then
break;
hMapping:=CreateFileMapping(hFile,nil,PAGE_READWRITE,0,GetFileSize(hFile,nil),ni l);
if hMapping=INVALID_HANDLE_VALUE then
break;
Data:=MapViewOfFile(hMapping,FILE_MAP_ALL_ACCESS,0,0,GetFileSize(hFile,nil));
i:=strlen(Data);
В строчке i:=strlen(Data) возникает ошибка (Data: PChar). Проверялось также на примере, который идет к книге Тейксейра и Пачеко Delphi5 Руководство разработчика - FileSRCH (тут вылетает в момент StrPos, где в качестве аргумента используется переменная, указывающая на результат MapViewOfFile).
Судя по всему как-то не "так" выполняется FData:=MapViewOfFile для файлов размером 4096,8192... Почему-то все функции, которые предназначены для работы с PChar вылетают с ошибкой (приведение переменной Pointer к PChar выполнялось)...
Заранее благодарен за ответ.
Юрий.
← →
Dimka Maslov © (2008-11-29 12:19) [1]1.
Вопрос: что делает функция strlen?
Ответ: с ч и т а е т количество байт от переданного ей указателя до первого нулевого байта.
Следовательно, если нулевой байт не обнаружен внутри выделенного блока памяти, функция выходит за эти пределы. А доступ туда запрещён, что и вызывает AV.
2.
Если произошла ошибка и Data = nil, то, естественно, все обращения к ней тоже будут генерировать AV.
← →
man Yury (2008-11-29 12:35) [2]Я пробовал добавлять в код
GetMem(Data,GetFileSize(hFile,nil)+1);
FillChar(Data^,GetFileSize(hFile,nil)+1,#0);
или
результат функции присваивал переменной Pointer(Fdata):=MapViewOfFile
Data:=PChar(FData);
inc(Data,GetFileSize(hFile,nil));
Data^:=#0;
результат одинаков Access violation at 0040AD6F accessing 00E22000
дело в том что я взял пример из Тейксейра проверил там тоже ошибка на файле размером 4096 в строке strpos ....
Спасибо за ответ
Юрий
← →
Palladin © (2008-11-29 12:42) [3]какого типа Data ?
← →
man Yury (2008-11-29 12:45) [4]Data - PChar
также пробовал вариант приведения Data:=PChar(MapViewOfFile...)
скажите что попробовать - попробую ... посто незнаю что уже делать ...
← →
man Yury (2008-11-29 12:47) [5]по ссылке http://www.delphikingdom.com/asp/answer.asp?IDAnswer=66905
можно найти пример который приводит в своей книге Тейксейра Delphi5.Руководство разработчика - там тоже выскакивает ошибка....
← →
Anatoly Podgoretsky © (2008-11-29 13:03) [6]> man Yury (29.11.2008 12:05:00) [0]
Нельзя использовать PChar функции к переменной Data, особенно не понимая как все это работает. Результатом как раз и будет Access violation
← →
Anatoly Podgoretsky © (2008-11-29 13:05) [7]> man Yury (29.11.2008 12:35:02) [2]
А это полное непонимания принципов работы MapViewOfFile и PChar, тут вообще дурость написана.
Кроме того, как это принято у начинающих никакого анализа на ошибки, они уверены, что в их программах никогда не будет ошибок.
← →
sniknik © (2008-11-29 13:13) [8]> по ссылке http://www.delphikingdom.com/asp/answer.asp?IDAnswer=66905
> можно найти пример
и там же можно увидеть... если читать ответы конечно.
29-11-2008 02:59
Строка типа PChar обязана завершаться нулём. Я не знаю, что там у вас в файле, но, похоже, что он текстовый и ни одного нуля там нет. Память процессу выделяется блоками по 4 илобайта и заполняется нулями. Если размер файла не кратен блоку, в адресном пространстве процесса после данных маппированного файла остются эти нули, которые и служат признаком конца строки. Когда же размер файла кратен размеру блока, при поиске завершающего нуля функции выскакивают за пределы этого блока, а там - память, которая не была отображена в адресное пространоство процесса. Отсюда и AV.
Модератор КС Антон Григорьев
← →
Leonid Troyanovsky © (2008-11-29 13:47) [9]
> man Yury (29.11.08 12:05)
Попробуй функцию, которая ищет подстроку в стриме:
function FindPos(Stream: TStream; var APos: Int64; const Substr: String; const BufSize: Longint): Boolean;
var
s: string;
nb, fpos, buflen : Longint;
lenss : Longint;
begin
Result := False;
lenss := Length(substr);
buflen := BufSize + lenss - 1;
SetLength(s, buflen);
Stream.Position := APos;
nb := Stream.Read(s[1], buflen);
if (nb < buflen) then
SetLength(s, nb);
fpos := Pos(Substr, s);
if fpos > 0 then
begin
APos := APos + fpos - 1;
Result := True;
Exit;
end
else
if (nb < buflen) then
Exit;
while Stream.Position < Stream.Size do
begin
Move(s[BufSize+1], s[1], lenss-1);
nb := Stream.Read(s[Lenss], BufSize);
if nb < BufSize then
SetLength(s, nb + lenss-1);
fpos := Pos(Substr, s);
if fpos > 0 then
begin
APos := Stream.Position - BufSize - lenss + fpos;
Result:= True;
Exit;
end;
end;
end;
Она лучше, чем StrPos, потому как может найти хоть #0#1#2#3.
Хотя, если работать с файлами, лучше сделать наследника TFileStream,
снабдив его подобным методом.
--
Regards, LVT.
← →
man Yury (2008-11-29 13:56) [10]Спасибо, согласен с Вами -))
исправил так (PData - Pointer) сделал как по учебнику -)))
Pdata:=MapViewOfFile ....
getmem(Data,GetFileSize(hFile,nil)+1);
fillchar(Data^,GetFileSize(hFile,nil),#0);
move(PData^,Data^,GetFileSize(hFile,nil));
Других путей нет (на сколько оптимален код)? Я имею ввиде чтобы PData и Data имели один указатель ...
to Anatoly Podgoretsky
никакого анализа на ошибки,
можно уточнить какого анализа не хватает (следующей строкой проверялась переменная Data на nil)
Юрий
← →
man Yury (2008-11-29 14:04) [11]
> Попробуй функцию, которая ищет подстроку в стриме:
Спасибо. Дело в том, что я работаю с файлами - найти строку, проанализировать содержимое ... а так как их многова-то бывает тыс.1-1,5 , то хочется оптимизировать программу, исключив утечки памяти и ошибки.
Юрий.
← →
Leonid Troyanovsky © (2008-11-29 14:17) [12]
> man Yury (29.11.08 14:04) [11]
>
> > Попробуй функцию, которая ищет подстроку в стриме:
>
> Спасибо. Дело в том, что я работаю с файлами - найти строку,
> проанализировать содержимое ... а так как их многова-то
> бывает тыс.1-1,5
И чего ты думаешь, что поиск в проекции всего файла будет быстрей?
Сомневаюсь.
Если размер файлов не превышает, скажем 1 мегабайта,
то можно поступать еще проще - считывать целиком файл в буфер
достаточного размера и искать там.
--
Regards, LVT.
← →
Leonid Troyanovsky © (2008-11-29 14:21) [13]
> man Yury (29.11.08 13:56) [10]
> Pdata:=MapViewOfFile ....
> getmem(Data,GetFileSize(hFile,nil)+1);
> fillchar(Data^,GetFileSize(hFile,nil),#0);
> move(PData^,Data^,GetFileSize(hFile,nil));
>
> Других путей нет (на сколько оптимален код)?
Да во-ще неоптимален.
Одно распределение для проекции, и еще для копии, и все ради StrPos.
Я ж показал оптимальный.
--
Regards, LVT.
← →
Leonid Troyanovsky © (2008-11-29 14:25) [14]
> Leonid Troyanovsky © (29.11.08 14:17) [12]
> то можно поступать еще проще - считывать целиком файл в
> буфер
> достаточного размера и искать там.
Т.е., выбрать достаточный bufsize, и фунция будет отрабатывать
без цикла while.
--
Regards, LVT.
← →
Slym © (2008-11-29 16:01) [15]man Yury (29.11.08 13:56) [10]
вот нафега выделять память, заливать ее нулями, потом мувить туда другую область памяти? чтобы потом дальше работать как с памятью?
если тебе строка нужна, то
DataSize:=GetFileSize(hFile,nil);
Data:=MapViewOfFile(...
SetString(str,Data,DataSize);
НО ЗОЧЕМ?
проще без мапинга
SetLength(Str,DataSize);
SetLength(Str,ReadFile(hFile,PChar(Str)^,DataSize));
← →
Slym © (2008-11-29 16:12) [16]если ищем строку то можно MapViewOfFile+SearchBuf там есть "ограничитель"
← →
Anatoly Podgoretsky © (2008-11-29 17:08) [17]
> to Anatoly Podgoretsky
> никакого анализа на ошибки,
>
> можно уточнить какого анализа не хватает (следующей строкой
> проверялась переменная Data на nil)
Нигде не наблюдается, но и этого не достаточно, надо еще проверить на саму ошибку и диагностику выдать пользователю.
← →
man Yury (2008-12-01 12:35) [18]Добрый день,All.
Извините, в субботу рабочий день закончился - поэтому не отвечал...
Программа, в которой используется приведенный выше фрагмент, мониторит определенный директорий на появление в нем файлов ... при появлении файлов, размер которых может быть от 512 байт до пару мегабайт, она ищет кодовые слова, через n-символов от кодового слова читать значение и дальше записывает это все в базу... Именно поэтому я остановился на маппировании файла.... просто не хочется читать большой файл в память... может есть какая-нибудь другая альтернатива...?
← →
clickmaker © (2008-12-01 13:02) [19]> просто не хочется читать большой файл в память... может
> есть какая-нибудь другая альтернатива.
можно мапить не сразу весь файл, а по частям.
см. dwFileOffsetHigh dwFileOffsetLow в MapViewOfFile()
← →
Leonid Troyanovsky © (2008-12-01 13:10) [20]
> man Yury (01.12.08 12:35) [18]
> все в базу... Именно поэтому я остановился на маппировании
> файла.... просто не хочется читать большой файл в память.
А маппировать большой файл хочется?
В чем ты видишь отличие?
> может есть какая-нибудь другая альтернатива...?
Мы ее не скрывали.
--
Regards, LVT.
← →
man Yury (2008-12-01 13:28) [21]
> А маппировать большой файл хочется?
> В чем ты видишь отличие?
Просто маппирование большого файла выполняется быстрее, чем что-либо из пока предложенного ... правда я не могу сказать насколько быстро осуществляется поиск по переменной типа PChar или по строковой - не проверял... с Вашим кодом я пока еще не разбирался ...
Юрий
← →
Leonid Troyanovsky © (2008-12-01 14:05) [22]
> man Yury (01.12.08 13:28) [21]
> Просто маппирование большого файла выполняется быстрее,
> чем что-либо из пока предложенного ...
Ну, это ты тоже пока не проверял.
--
Regards, LVT.
← →
man Yury (2008-12-01 14:18) [23]Свой вариант
move(PData^,Data^,GetFileSize(hFile,nil));
проверял... правда все относительно в этом мире -))) и проверялось это на файле 70 мб -))
Юрий
← →
Leonid Troyanovsky © (2008-12-01 14:22) [24]
> man Yury (01.12.08 14:18) [23]
> Свой вариант
> move(PData^,Data^,GetFileSize(hFile,nil));
Этот вариант никто здесь, IMHO, и не советовал.
--
Regards, LVT.
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2009.01.11;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.005 c