Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2004.12.12;
Скачать: [xml.tar.bz2];

Вниз

FileMapping   Найти похожие ветки 

 
IronRat   (2004-10-30 18:21) [0]

Привет,
была поставлена задача поиск строки в файлах, и в общем-то все работает, до момента, когда моя программа при переборе файлов натыкается на STRING.H из библиотеки BC3.1 :(
вылетает на этой строке
      Address := pChar(MapFilePointer);
      i := Pos(SearchString,Address);
точнее на i := Pos(SearchString,Address). Вот.
Вылетает при любой дислокации файла STRING.H.
Было ощущение, что Pos возвращает слишком большое значение, но int64 для i не помогло. Да и сам файл всего 8 кило.
Подскажите, в чем может быть проблема?


 
Игорь Шевченко ©   (2004-10-30 18:27) [1]


> моя программа вылетает на этой строке



> Подскажите, в чем может быть проблема?


В программе, разумеется.

Я бы посоветовал поиск организовать иначе, чем использованием функции Pos, например, побайтовым сравнением, с учетом размера спроецированного файла, чтобы при сравнении не выйти за его границу.


 
Ihor Osov'yak ©   (2004-10-30 21:58) [2]

try it:

function GetViewFile(aFileName: string; var aBuff: pointer; var aSize: integer): boolean;
var
 fh: THandle; // file handle
 fm: THandle; // File mapping handle

begin
 result := false;
 aBuff := nil;
 aSize := 0;

 if not FileExists(aFileName) then
   exit;

 fh := CreateFile(PChar(aFileName), GENERIC_READ, 0, nil,
   OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);
 if fh = INVALID_HANDLE_VALUE then
   exit;

 aSize := GetFileSize(fh, nil);

 fm := CreateFileMapping(fh, nil, PAGE_READONLY, 0, 0, nil);
 CloseHandle(fh);

 if fm = 0 then
   exit;

 aBuff := MapViewOfFile(fm, FILE_MAP_READ, 0, 0, 0);
 result := assigned(aBuff);
end;

function FindSubstrInBuff(const Buff: pointer; SubStr: AnsiString; DimBuff: integer): integer;
asm
       // EAX = Buff, EDX = addr SubSTR, ECX = DimBuff
       PUSH EDI
       PUSH ESI
       PUSH EBX
       PUSH EAX
       OR EAX,EAX
       JE @@2  // Buff = nil
       OR EDX,EDX
       JE @@2  // SubStr = nil
       OR ECX,ECX
       JE @@2  // size = nil

       MOV EBX, ECX

       SUB EBX,[EDX-4]
       JL @@2
       INC EBX

       MOV ECX,EBX
       MOV EBX,[EDX-4]
       DEC EBX
       MOV EDI,EAX
@@1: MOV ESI,EDX
       LODSB
       REPNE SCASB
       JNE @@2
       MOV EAX,ECX
       PUSH EDI
       MOV ECX,EBX
       REPE CMPSB
       POP EDI
       MOV ECX,EAX
       JNE @@1
       LEA EAX,[EDI-1]
       POP EDX
       SUB EAX,EDX
       INC EAX
       JMP @@3
@@2: POP EAX
       XOR EAX,EAX
@@3: POP EBX
       POP ESI
       POP EDI
end;


использование - сначала  GetViewFile, потом FindSubstrInBuff.
Помнить о UnmapViewOfFile для указателя, полученого через var aBuff: pointer..


 
Ihor Osov'yak ©   (2004-10-30 22:01) [3]

да, кажется нужно также закрывать fm, то есть
вместо

aBuff := MapViewOfFile(fm, FILE_MAP_READ, 0, 0, 0);
result := assigned(aBuff);

должно быть

aBuff := MapViewOfFile(fm, FILE_MAP_READ, 0, 0, 0);
CloseHandle(fm);
result := assigned(aBuff);

иногда полезно постить куски кода, над которыми сейчас работаешь :-).


 
IronRat   (2004-10-30 23:54) [4]

я ассемблер конечно люблю :)
но при случае предпочитаю обходиться без него...
исправляюсь к последнему замечанию ("иногда полезно постить куски кода, над которыми сейчас работаешь :-)."):

function FileMappingFunc(FileName: string; SearchString: string): boolean;
begin
hFile := CreateFile(pChar(FileName), GENERIC_READ, FILE_SHARE_READ and FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if hFile <> INVALID_HANDLE_VALUE then
 begin
  hMapFile := CreateFileMapping(hFile, nil, PAGE_READONLY, 0, 0, nil);
  if hMapFile <> 0 then
   begin
    MapFilePointer := MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
    if MapFilePointer <> nil then
     begin
      Address := pChar(MapFilePointer);
      i := Pos(SearchString,Address);
      UnMapViewOfFile(MapFilePointer);
     end
    else
     SubStr := False;
    CloseHandle(hMapFile);
   end;
  if i = 0 then
   SubStr := False
  else
   SubStr := True;
  CloseHandle(hFile);
 end                          
else
 SubStr := False;
end;
end;

проблема явная, провереная не на один раз:
      i := Pos(SearchString,Address);
тут он падает на 1 файле из миллиона (образно). я нашел 2 таких файла. на мой взгляд они _НИЧЕМ_ не примечательны.


 
GuAV ©   (2004-10-31 00:27) [5]


> function FindSubstrInBuff(const Buff: pointer; SubStr:
> AnsiString; DimBuff: integer): integer;

http://dennishomepage.gugs-cats.dk/FastCodeProject.htm

ищите там PosChallenge ;)


 
IronRat   (2004-10-31 01:40) [6]

GuAV нашел, посмотрел, не понял, как это может помочь мне...
:(


 
GuAV ©   (2004-10-31 01:52) [7]

Блин, забыл написать, не Вам, а 2 Ihor Osov"yak. Он написал свою Pos на asm, так я указал где ещё лучше найти.


 
Ihor Osov'yak ©   (2004-10-31 03:54) [8]

2 [7] GuAV ©   (31.10.04 01:52)

Спасибо. Код FindSubstrInBuff, собственно не совсем мой, я его в свое время увидел на каком-то форуме, немного адаптировал.. Автора оригинального кода к сожалению не запомнил...

2  IronRat  
> вылетает на этой строке

знаете, было бы не лишним указать текст сообщения об ошибке. Это во первых. Во вторых, желательно упомянуть тип SearchString,Address...
Понятно, что это либо PChar либо стринг. Но и в том и в том случае в Вашем коде будут присутсвовать неявные копирования блоков памяти в процессе преобразования между строками вида PChar и string, что значительно снижает быстродействие, то есть выиграш от отображения файла в память.
Также не совсем оптимален набор атрибутов при открытии файла. Но это так, между прочим..

А теперь к основному вопросу - почему вылет.. Кстати, файлик то читается? Попробуйте его скопировать куда-то.. Я это к тому, что в случае, если Address - PChar, то реальная подчитка файла будет осуществлятся при преобоазоварнии PChar в стринг в процессе подготовки параметров для Pos вот в этой чудненькой строчке -
 i := Pos(SearchString,Address);
и здесь вполне может быть ошибка ввода-вывода..


 
IronRat   (2004-10-31 11:12) [9]

2 Ihor Osov"yak:
да, Address типа PChar, а SearchString типа string...
видимо проблема в этом, но избавиться-то от нее как?


 
IronRat   (2004-10-31 11:17) [10]

2 Ihor Osov"yak:
кстати, я уже писал, что файл читается.
а ошибка происходит при любой дислокации файла.
ошибка такая:
"Project Search.exe raised exception class EAccessViolation with message "Access violation at address 04044aAF in module "Search.exe". Read of address 00A92000" Process stopped."


 
Ihor Osov'yak ©   (2004-10-31 12:17) [11]

2 [10] IronRat   (31.10.04 11:17)

блин..
ларчик открывается довольно просто. Для нормального преобразования PChar в string (а это происходит перед передачей параметров в Pos, я веду спич о Address)  нужно чтобы первый оканчивался символом с кодом 0. А у Вас - это не совсем так. Вся область памяти, на которую указывает Address в процессе преобразования будет сканироваться до встречи первого 0, и все, что встретилось до того - будет интерпритироваться как строка. То есть до отражения файла в процессе преобразования будет присоединяться куча всякого хлама, до встречи первого 0-символа после конце отражения. В случае с STRING.H Вам просто "повезло"   - просто в области хлама 0-символ не был встречен и Вы нарвались на границу распределенного блока памяти. Вполне возожно, что при мапировании файлов память становится доступной блоками, размер которых кратен страницам +  размер соотв. файла - кратен странице и следовательно сразу же за окончанием отражения - память не распределена (это версия) - а функция преобразования PChar в ансистринг родолжает свою работу. И как следствие - Access violation..

итого резюме - возьмите код, который я Вам привел и не партесь. Хотя бы потому что ваша реализация очень неоптимальна - выше я уже объяснал почему - ну и плюс неочевидная ошибка, также которая прокоментирована
абзацем выше..

зы. собственно я немного больше разжевал то, что уже было концептуально сформулировано в [1]..


 
Ihor Osov'yak ©   (2004-10-31 12:20) [12]

Вполне возожно -> Вполне возможно...
и даже не возможно - а очевидно, что так - так как у вас результат повторяем.. Посмотрите размер этого STRING.H - могу поспорить, что он кратен 4096 :-)


 
IronRat   (2004-10-31 12:54) [13]

2 Ihor Osov"yak:
:)))
8192...
да.
Спасибо большое. Ошибка ясна, будем исправляться :)


 
Ihor Osov'yak ©   (2004-10-31 13:15) [14]

2 IronRat

Вы всеже откажитесь от использования Pos (в основном из-за того, что там как не крути, не избежать преобразования PChar -> string, а это время - это для Вас наверное критично, раз начали отражения делать..). Для экспреиманта - сравните быстродействие с Pos и без - например мою реализацию (один из вариантов - запустите цыкл с несколькими тысячими реализаций). Результат Вас должен впечатлить.
Еще - реализации, которые по ссылке от  [5] GuAV © - значительно более быстрые - но они все же ориентированы на работу со String, а у Вас - буфер. Если делать преобразование - то снова потери, которые сводят на нет все преимущества более быстрой реализации.  Посему отталкивайтесь от кода, приведенного мной, или займитесь адаптацией (переход от string к буферу с указанием размера) от ссылки [5] GuAV - но там код далеко не тривиальный.


 
Ihor Osov'yak ©   (2004-10-31 13:16) [15]

несколькими тысячими реализаций - несколькими тысячими итераций.
Извините.


 
IronRat   (2004-10-31 13:50) [16]

2 Ihor Osov"yak ©:
с ассемблером я вряд ли разберусь :(
да и время поиска для меня не так уж критично...
предпочтительней, наверно, это:
"или займитесь адаптацией (переход от string к буферу с указанием размера)".
Но что-то я пока не представляю как это сделать.


 
IronRat   (2004-10-31 13:55) [17]

так?
function BinaryToStr(PBuffer:Pointer;size:integer;Delimiter:char):string;
{преобразование последовательности байтов в строку
PBuffer - указатель на начало двоичной области
Size - количество байт}
var
s:string;
i:integer;
begin
result:="";
for i:=0 to Size-1 do begin
 s:=inttohex((PByteArray(PBuffer))^[i],2);
 if (Delimiter<>#0) then s:=s+Delimiter;
 Result:=Result+s;
end;
if (Result<>"")and(Delimiter<>#0)then setlength(Result,length(Result)-1);
end;

код не мой... :)


 
IronRat   (2004-10-31 14:12) [18]

или блин... не знаю даже.
наверно не надо в ansistring преобразовывать... она же ограничена 2^31... а мне бы без ограничений, не зря же я отображение использовал.


 
Ihor Osov'yak ©   (2004-10-31 14:57) [19]

2 [17] IronRat   (31.10.04 13:55)

блин, что за ахинея. Я в шоке. Это с привода  function BinaryToStr(PBuffer:Pointer;size:integer;Delimiter:char):string;
не вобще, а применительно к Вашему случаю.  Это во первых. Во вторых - хотел бы я посмотреть, как Вы сматируете в память файл, размером больше  "2^31". В Win32 во всяком случае.  

Повторяю раз четверый наверно - ничего преобразовывать не нужно. Искать в буфере без преобразований. С учетом размера буфера. Один из примеров реализации такого поиска я привел. Берите и используйте. И извините за прямоту - у меня подозрения, что Ваши познания в паскале не сильно убежали от Ваших познаний в ассемблере.
И еще. Большая просьба. Если уже немного ушли от компонентобросания - почитайте книжки. Не Архангельского. Последствия чтения последнего автора порою неисправимы за всю последующую жызнь.


 
IronRat   (2004-10-31 15:04) [20]

2 Ihor Osov"yak:
Спасибо.


 
Ihor Osov'yak ©   (2004-10-31 15:21) [21]

2 [20] IronRat   (31.10.04 15:04)

А знаете, я почему-то верю, что у Вас все получится.



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2004.12.12;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.039 c
8-1094651546
SNV888
2004-09-08 17:52
2004.12.12
проигрывание MOD файлов


1-1101744749
Сор
2004-11-29 19:12
2004.12.12
TextFile


14-1101281444
Vlad Oshin
2004-11-24 10:30
2004.12.12
Просветите, экономисты, если времени не жалко


3-1100508460
neat
2004-11-15 11:47
2004.12.12
TDBLookupComboBox


14-1100852166
msguns
2004-11-19 11:16
2004.12.12
"Потрепанный орешник"





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский