Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.01.11;
Скачать: CL | DM;

Вниз

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;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.015 c
2-1227969919
snake-as
2008-11-29 17:45
2009.01.11
Поиск в поткаталогах


15-1226659411
sefon
2008-11-14 13:43
2009.01.11
У кого есть подшивка журнала Моделист-Конструктор ?


1-1205387717
Maxick
2008-03-13 08:55
2009.01.11
TIBataBase и DLL


2-1227701460
2B
2008-11-26 15:11
2009.01.11
Переделать код


2-1227686798
Trinimak
2008-11-26 11:06
2009.01.11
data diagram