Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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
1-1205651887
Megatron
2008-03-16 10:18
2009.01.11
Hint в ComboBox


2-1227856798
Андрей Алекс.
2008-11-28 10:19
2009.01.11
Сохдать Pages в PageControl


2-1227868679
Scot Storch
2008-11-28 13:37
2009.01.11
директива absolute


8-1189091515
Дмитрий Стрункин
2007-09-06 19:11
2009.01.11
Как считать определенную область экрана


3-1212598398
Цукор5
2008-06-04 20:53
2009.01.11
FireBird 1.5 &amp; Vista ?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский