FindNext - Access violation

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

Ответить
author
незнакомец
Сообщения: 5
Зарегистрирован: 09.01.2010 15:31:23

FindNext - Access violation

Сообщение author »

Добрый день.

Код: Выделить всё

  function TLocator.Locate( Path : String ) : Boolean;
  var
    Info : TSearchRec;
    i : Integer;
  begin
    i := 0;
    if ( FindFirst( Path + '*', faAnyFile AND faDirectory, Info ) = 0 ) then
      repeat
        if Info.Name = '.' then
          continue;
        List[i].name := Info.Name;
        List[i].fullpath := Path + Info.Name;
        if ( Info.Attr AND faDirectory ) = faDirectory then
          begin
            List[i].directory := true;
            List[i].fullpath := List[i].fullpath + '/';
          end;
        i := i + 1;
      until ( FindNext( Info ) <> 0 );
    FindClose( Info );

    if i = 0 then
      Locate := false
    else
      begin
        Root := Path;
        Count := i - 1;
        Locate := true;
      end;
  end;


При первом вызове отрабатывает, при втором валится на FindNext, вне зависимости от директории.
Не могу понять в чем дело. Может быть кто подскажет. Спасибо.

An unhandled exception occurred at $0805A086 :
EAccessViolation : Access violation
$0805A086
$0804A24F
$08072670
$08060ECF
$08060B13
$08048BAB
$08048C4D

fpc 2.2.0
Аватара пользователя
AbakAngelSoft
постоялец
Сообщения: 273
Зарегистрирован: 06.08.2008 19:28:26
Откуда: Краснодар
Контактная информация:

Сообщение AbakAngelSoft »

Валится наверное на List[i]? Где создаются элементы массива или списка?
author
незнакомец
Сообщения: 5
Зарегистрирован: 09.01.2010 15:31:23

Сообщение author »

валится там, где я написал

Код: Выделить всё

      repeat
        if i <> 0 then
          writeln( 'FindNext end' );
        if Info.Name = '.' then
          continue;
        List[i].name := Info.Name;
        List[i].fullpath := Path + Info.Name;
        if ( Info.Attr AND faDirectory ) = faDirectory then
          begin
            List[i].directory := true;
            List[i].fullpath := List[i].fullpath + '/';
          end;
        i := i + 1;
        writeln( 'FindNext begin' );
      until ( FindNext( Info ) <> 0 );


FindNext begin
An unhandled exception occurred at $0805A086 :
EAccessViolation : Access violation
$0805A086
$0804A24F
$08060F0C
$08060B13
$08048BAB
$08048C4D
Аватара пользователя
Astralis
новенький
Сообщения: 45
Зарегистрирован: 06.06.2007 20:33:05
Откуда: Tvercity-Annet
Контактная информация:

Сообщение Astralis »

можете заметить, что

Код: Выделить всё

faAnyFile AND faDirectory = faDirectory

так что в вашем примере будут только каталоги. теоретически может существовать не только каталог . но каталог .. всех их надо пропускать,
проверять на соответствие атрибутов каталогу тоже наверное лишнее (раз тут могут быть исключительно каталоги).
список list должен уже быть создан и инициализирован и все его элементы сконструированы, но мне интересно, а как вы заранее узнали его размер. попробуйте прогнать ту программу без list
код инициализации list в студию
Аватара пользователя
AbakAngelSoft
постоялец
Сообщения: 273
Зарегистрирован: 06.08.2008 19:28:26
Откуда: Краснодар
Контактная информация:

Сообщение AbakAngelSoft »

Автор же уверен что с list все в порядке :) ! Зачем его инициализировать? Это все разработчики lazarus виноваты! :)
Odyssey
энтузиаст
Сообщения: 580
Зарегистрирован: 29.11.2007 16:32:24

Сообщение Odyssey »

author писал(а):An unhandled exception occurred at $0805A086 :
EAccessViolation : Access violation
$0805A086
...

Хм, если включить в опциях проекта "Выдавать номера строк в ошибках времени исполнения", то по идее рядом с адресами должны будут появиться названия вызываемых функций и номера строк. С этой информацией было бы проще понять в чём дело.

И для чистоты эксперимента, было бы здОрово поставить writeln('FindNext end'); следом за циклом. Мало ли, может быть FindNext уже возвращает что-то отличное от нуля, и программа падает после выхода из цикла.
sign
энтузиаст
Сообщения: 1131
Зарегистрирован: 30.08.2009 09:20:53

Сообщение sign »

Ясно дело, с List наглючил, потому и не желает показать нам весь код.
Padre_Mortius
энтузиаст
Сообщения: 1265
Зарегистрирован: 29.05.2007 17:38:07
Откуда: Спб

Сообщение Padre_Mortius »

Интересно кто-нить из отписавшихся проверил код? )))

Если я правильно понял это не весь код. Вот уж не знаю, что хочет сделать автор, но проблемы в алгоритме тоже есть. Некоторые файлы данный алгоритм считает за папки и сканирует только текущую папку.

Для начала думаю стоит автора отправить почитать Базу Знаний http://freepascal.ru/forum/viewtopic.php?f=35&t=5013
author
незнакомец
Сообщения: 5
Зарегистрирован: 09.01.2010 15:31:23

Сообщение author »

Astralis
с чего Вы взяли что будут обрабатываться только каталоги?
если внимательно прочитать код, то видно, что в случае, если каталог, то просто пометить что это каталог, и далее обработка следующего элемента (файла или каталога, без разницы)

AbakAngelSoft
с List[] все в порядке

Odyssey
естественно я это проверял через writeln, падало именно на FindNext
а за опцию спасибо, удобная штука, не использовал, так как компилю из консоли

sign
см выше

Padre_Mortius
Padre_Mortius писал(а):Некоторые файлы данный алгоритм считает за папки и сканирует только текущую папку

вот тут можно поподробнее?

2all
Проблема решилась после нахождения ошибки в другом месте кода - после StrAlloc забыл StrDispose,
и так при нескольких повторных вызовах того кода. Странно что всплыло это именно на FindNext.
чем то напоминает приколы в Си
Padre_Mortius
энтузиаст
Сообщения: 1265
Зарегистрирован: 29.05.2007 17:38:07
Откуда: Спб

Сообщение Padre_Mortius »

вас самого данный кусок кода не смущает?

Код: Выделить всё

       List[i].fullpath := Path + Info.Name;
        if ( Info.Attr AND faDirectory ) = faDirectory then
          begin
            List[i].directory := true;
            List[i].fullpath := List[i].fullpath + '/';
          end;

т.е. Вы сначала записываете в параметр List[i].fullpath путь к элементу, а потом проверяете атрибут fadirectory и меняете его. Имхо не совсем удачно. Может конечно я где-то ошибаюсь, но конструкция следующего вида будет более уданой

Код: Выделить всё

        if ( Info.Attr AND faDirectory ) = faDirectory then
          begin
            List[i].directory := true;
            List[i].fullpath := List[i].fullpath + '/';
          end else        List[i].fullpath := Path + Info.Name;
author
незнакомец
Сообщения: 5
Зарегистрирован: 09.01.2010 15:31:23

Сообщение author »

Padre_Mortius
тогда Ваш код тоже не очень удачен, нужно так)

Код: Выделить всё

        if ( Info.Attr AND faDirectory ) = faDirectory then
          begin
            List[i].directory := true;
            List[i].fullpath := Path + Info.Name + '/';
          end
        else
           begin       
             List[i].directory := false;
             List[i].fullpath := Path + Info.Name;
           end;


но это все мелочи
sign
энтузиаст
Сообщения: 1131
Зарегистрирован: 30.08.2009 09:20:53

Сообщение sign »

Тоже мелочь, но....

Код: Выделить всё

    List[i].fullpath := Path + Info.Name;
    List[i].directory := (Info.Attr AND faDirectory) = faDirectory;
    if List[i].directory then List[i].fullpath := List[i].fullpath + '/';
author
незнакомец
Сообщения: 5
Зарегистрирован: 09.01.2010 15:31:23

Сообщение author »

sign
а Padre_Mortius ответит на это
Padre_Mortius писал(а):т.е. Вы сначала записываете в параметр List[i].fullpath путь к элементу, а потом проверяете атрибут fadirectory и меняете его.

:lol:

Добавлено спустя 59 секунд:
в общем всем спасибо, прога уже работает и радует меня
Ответить