Access Violation в TApplication.DoIdleActions;

Вопросы программирования и использования среды Lazarus.

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

Access Violation в TApplication.DoIdleActions;

Сообщение Climber » 24.08.2009 13:58:14

Очень нужна помощь! В приложении давно уже был замечен "блуждающий" Access Violation. Сегодня удалось зафиксировать последовательность действий, посте которой ошибка возникает со 100% вероятностью. Поскольку проект уже довольно большой, пока все приводить не буду... Кратко - пользователь подключается к БД, получает список клиентов, тыкает в определенный столбец, чтобы отсортировать список, потом вызывает дочернее окно, закрывает окно и ловит AV.
Вот мой код:
Код: Выделить всё
procedure TMainForm.SearchClients;
begin
  Application.CreateForm(TSearchForm, SearchForm);
  if SearchForm.ShowModal=mrOK then
     ShowSearchResults;
  FreeAndNil(SearchForm);
end;
Эта функция вызывается нажатием на кнопку. Отрабатывает до конца без проблем. После этого возникает AV в модуле application.inc:
Код: Выделить всё
procedure TApplication.DoIdleActions;
var
  i: Integer;
  CurForm: TCustomForm;
  AForm: TForm;
begin
  for i := 0 to Screen.CustomFormCount - 1 do begin
    CurForm:=Screen.CustomForms[I];
    if CurForm.HandleAllocated and CurForm.Visible and CurForm.Enabled then
      CurForm.UpdateActions;
  end;
  if FFormList<>nil then begin
    for i:=0 to FFormList.Count-1 do begin
      AForm:=TForm(FFormList[i]);
      if AForm.FormStyle=fsSplash then   // ошибка тут
        AForm.Hide;
    end;
  end;
end;
У меня есть версия, что в этом месте в AForm передается ссылка на только что уничтоженную форму, ссылка на которую по какой-то неизвестной причине осталась в FFormList. Причем ошибка возникает не всегда, а только изредка.
Вопросы остаются старые - кто виноват и что делать? Ну или хотя бы в каком направлении копать...

В проекте используется: Lazarus 0.9.27.20724, WinXP, компоненты zeos 6.6.5.
Climber
постоялец
 
Сообщения: 415
Зарегистрирован: 03.06.2007 20:09:57
Откуда: Москва

Re: Access Violation в TApplication.DoIdleActions;

Сообщение GAMER » 07.10.2010 01:11:42

Свежий Лазарус. Те же грабли. Понять логику ошибки не могу :(
Аватара пользователя
GAMER
энтузиаст
 
Сообщения: 627
Зарегистрирован: 06.08.2008 13:41:07
Откуда: Ужгород-Днепр, Украина

Re: Access Violation в TApplication.DoIdleActions;

Сообщение dunin » 07.10.2010 10:33:06

GAMER писал(а):Понять логику ошибки не могу :(

ИМХО FFormList пустой.

Я бы так попробовал
Код: Выделить всё
...
  if FFormList<>nil then begin
    for i:=0 to FFormList.Count-1 do begin
    // -------------------------
    showmessage('FFormList['+unttostr(i)+'] = '+TForm(FFormList[i]).Name);
    // -------------------------
      AForm:=TForm(FFormList[i]);
      if AForm.FormStyle=fsSplash then   // ошибка тут
        AForm.Hide;
    end;
...


Добавлено спустя 3 минуты 21 секунду:
dunin писал(а):+unttostr(i)+

intToStr разумеется. :?
Аватара пользователя
dunin
энтузиаст
 
Сообщения: 634
Зарегистрирован: 02.05.2007 13:18:11
Откуда: Тољя††и

Re: Access Violation в TApplication.DoIdleActions;

Сообщение GAMER » 07.10.2010 11:24:33

AV выскакивает. Или это Лазарус нужно пересобирать?
Аватара пользователя
GAMER
энтузиаст
 
Сообщения: 627
Зарегистрирован: 06.08.2008 13:41:07
Откуда: Ужгород-Днепр, Украина

Re: Access Violation в TApplication.DoIdleActions;

Сообщение dunin » 07.10.2010 11:32:20

GAMER писал(а):AV выскакивает. Или это Лазарус нужно пересобирать?

Все правильно
showmessage('FFormList['+unttostr(i)+'] = '+TForm(FFormList[i]).Name);

А объекта типа TForm там нет. Попробовать как-то так что-ли...
showmessage('FFormList['+unttostr(i)+'] = '+TComponent(FFormList[i]).ClassName);

или просто посчитать сколько там
showmessage('FFormList['+unttostr(i)+']');
Аватара пользователя
dunin
энтузиаст
 
Сообщения: 634
Зарегистрирован: 02.05.2007 13:18:11
Откуда: Тољя††и

Re: Access Violation в TApplication.DoIdleActions;

Сообщение GAMER » 07.10.2010 11:46:22

Делал и так
showmessage('FFormList['+inttostr(i)+']');
Все то же самое.

Такое ощущение, что в самом FFormList какой-то глюк.

Добавлено спустя 2 минуты 10 секунд:
Кстати, если нужно, могу рассказать, как получить AV.
Аватара пользователя
GAMER
энтузиаст
 
Сообщения: 627
Зарегистрирован: 06.08.2008 13:41:07
Откуда: Ужгород-Днепр, Украина

Re: Access Violation в TApplication.DoIdleActions;

Сообщение dunin » 07.10.2010 12:55:49

А если таким финтом как-то извернуться?
Код: Выделить всё
...
for i:= 0 to Application.ComponentCount-1 do begin
    if Application.Components[i].ClassParent.ClassType = tForm then begin
    ...
    // дальнейшие проверки/действия с формой
    ...
    end;
end;
Аватара пользователя
dunin
энтузиаст
 
Сообщения: 634
Зарегистрирован: 02.05.2007 13:18:11
Откуда: Тољя††и

Re: Access Violation в TApplication.DoIdleActions;

Сообщение Sergei I. Gorelkin » 07.10.2010 13:01:29

GAMER писал(а):Такое ощущение, что в самом FFormList какой-то глюк.


Открываем файл lcl/include/application.inc, ищем слово FFormList. Очень быстро становится ясно, что любая форма (наследник TForm), созданная с помощью Application.CreateForm, добавляется в этот самый FFormList, но оттуда никогда и ничего не удаляется . Поэтому, если ты вручную удаляешь форму, созданную в Application.CreateForm, то AV получишь рано или поздно с гарантией.

Попробуй создавать форму так: SearchForm := TSearchForm.Create(Application)
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Access Violation в TApplication.DoIdleActions;

Сообщение GAMER » 07.10.2010 13:37:50

Это глюк Лазаруса и стоит ждать исправлений или нужно менять идеологию на SearchForm := TSearchForm.Create(Application)?

А что значит "вручную удалять форму"?

Application.CreateForm начал использовать после того, как где-то прочитал, что так более правильно. Ошибся?
Аватара пользователя
GAMER
энтузиаст
 
Сообщения: 627
Зарегистрирован: 06.08.2008 13:41:07
Откуда: Ужгород-Днепр, Украина

Re: Access Violation в TApplication.DoIdleActions;

Сообщение Mr.Smart » 07.10.2010 13:59:19

Если вам необходимо в процессе работы программы создавать и удалят формы, то используем TForm.Create.
А если форма создаётся один раз и не уничтожается в процессе то Application.CreateForm.

Добавлено спустя 1 минуту 5 секунд:
Хотя можно и в последнем случае не использовать Application.CreateForm, а удалять форму самому при завершении приложения.
Mr.Smart
долгожитель
 
Сообщения: 1796
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: Access Violation в TApplication.DoIdleActions;

Сообщение Sergei I. Gorelkin » 07.10.2010 14:47:01

GAMER писал(а):Это глюк Лазаруса и стоит ждать исправлений или нужно менять идеологию на SearchForm := TSearchForm.Create(Application)?

Ёж - птица гордая, пока не пнешь - не полетит. Наблюдаем за полетом: http://bugs.freepascal.org/view.php?id=17570

GAMER писал(а):А что значит "вручную удалять форму"?

Значит вызвать FreeAndNil(SearchForm) раньше завершения приложения.

GAMER писал(а):Application.CreateForm начал использовать после того, как где-то прочитал, что так более правильно. Ошибся?

viewtopic.php?f=5&t=5360&p=38646&hilit=application+createform#p38600

Добавлено спустя 1 час 7 минут 26 секунд:
Исправлено в svn ревизии 27602. Время исправления 32 минуты :)
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Access Violation в TApplication.DoIdleActions;

Сообщение GAMER » 07.10.2010 15:58:00

Sergei I. Gorelkin писал(а):Добавлено спустя 1 час 7 минут 26 секунд:
Исправлено в svn ревизии 27602. Время исправления 32 минуты :)


Быстренько они отреагировали :) Сейчас начну тестировать :)
Аватара пользователя
GAMER
энтузиаст
 
Сообщения: 627
Зарегистрирован: 06.08.2008 13:41:07
Откуда: Ужгород-Днепр, Украина


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 50

Рейтинг@Mail.ru