Форум: "Базы";
Текущий архив: 2004.08.22;
Скачать: [xml.tar.bz2];
ВнизAccessViolation при закрытии клиента Найти похожие ветки
← →
Manfred (2004-07-26 18:00) [0]Ситуация: midas на сокетах, база Access, технология ADO. В клиенте MDI Form. В ней одновременно открыты две формы MDI Child. Одна из форм содержит связь master-detail, два TClientDataset, два TDatasource, два TDBGridEh, другая форма один TClientDataset, TDataSource, TDBGridEh. Формы обращаются к разным таблицам базы. При закрытии клиента destroy для формы с одним гридом проходит нормально. Срабатывает OnActivate для другой формы, в котором происходит закрытие, смена текста SQL запроса, а потом открытие двух TClientDataset`ов. При открытии TClientDataset происходит AccessViolation. Почему...
Ошибка возникает при TClientDataset.open. Такой же баг на другой форме вылечился заменой Close,Open на Refreshe.
← →
Johnmen © (2004-07-26 18:09) [1]Потому, что практика работы с НД в OnActivate глубоко порочна.
← →
Manfred (2004-07-26 18:14) [2]Ваш выбор OnShow? :)
Я согласен,но всетаки почему проходит refresh и не проходит Close
Open Странно
← →
Johnmen © (2004-07-26 18:27) [3]1. Как выглядит код обработчика ?
2. Полный текст AV ?
← →
Manfred (2004-07-26 18:36) [4]procedure TMonitoringFrm.FormActivate(Sender: TObject);
begin
HeadClientDataSet.close;
MakeSQLForMarshrut;
HeadClientDataSet.Open;
Access violation at address 004FA560 in module "ClientApp.exe". Read of address 00000008.
ReisClientDataSet.close;
MakeSQLForReis;
ReisClientDataSet.Open;
end;
← →
Плохиш © (2004-07-26 18:49) [5]
> Manfred (26.07.04 18:36) [4]
Понятие такое есть "отладка". Вот и занимайся. А ошибка как всегда в 17й строке.
← →
Johnmen © (2004-07-27 09:22) [6]> Manfred (26.07.04 18:36) [4]
1. Что скрывается за MakeSQLForMarshrut ?
2. Как здесь удается обойти AV с пом. Refresh ?
← →
Manfred (2004-07-27 10:26) [7]To Плохих> Представляете я в курсе.
To Johmen> Дело не в MakeSqlForMarshrut.
Есть аналогичная ошибка с ClienDataSet который связан с таблицей а не запросом. Если у него стоит Close/open выдается таже ошибка
если сделать вот так:
if CityClientDataSet.state= dsInactive then
CityClientDataSet.Open
else CityClientDataSet.Refresh;
То проходит на ура.
Если трайсить после Open идет по DBGridEh модулям и в конце концов пишет вот такое:
---------------------------
Debugger Fault Notification
---------------------------
Project C:\Documents and Settings\Peter\??????? ????\Midas ?? Progr1\client\ClientApp.exe raised too many consecutive exceptions: "access violation at 0x00000000: read of address 0x00000000". Process Stopped. Use Step or Run to continue.
---------------------------
OK Help
---------------------------
← →
Johnmen © (2004-07-27 10:41) [8]Какие события прописаны для MonitoringFrm и HeadClientDataSet ?
Да, и ещё. Что означает "При закрытии клиента " ?
← →
Manfred (2004-07-27 10:54) [9]Закрытие - Если нажимают крестик у главного MDI окна программы клиента,когда открыты два дочерних окна и причем фокус ввода на другом окне ,не на том в OnActivate которого происходит ошибка.
У HeadClientDataSet нет обработчиков
Обработчики у формы:
//размеры формы из Инишника
procedure TMonitoringFrm.FormCreate(Sender: TObject);
begin
ReadFormSizeFromIni(nil,self);
end;
procedure TMonitoringFrm.FormActivate(Sender: TObject);
begin
if ListOfYearsClientDataSet.state= dsInactive then
ListOfYearsClientDataSet.Open
else ListOfYearsClientDataSet.Refresh;
if CityClientDataSet.state= dsInactive then
CityClientDataSet.Open
else CityClientDataSet.Refresh;
HeadClientDataSet.close;
MakeSQLForMarshrut;
HeadClientDataSet.Open;
ReisClientDataSet.close;
MakeSQLForReis;
ReisClientDataSet.Open;
end;
procedure TMonitoringFrm.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
Action:=cafree;
MonitoringFrm:=nil;
end;
//размеры формы в Инишник
procedure TMonitoringFrm.FormDestroy(Sender: TObject);
begin
WriteFormSizeToIni(nil, self.Name,FormRecordInit(self));
end;
← →
Johnmen © (2004-07-27 11:01) [10]Похоже всё дело в последовательности обрабатываемых сообщений для MDI-ной формы. Посмотри, какая она. Насколько помню, сначала придет дестрой, а потом придет активейт...
Короче, см.пост [1]. + к нему OnDeactivate.
← →
Manfred (2004-07-27 11:15) [11]Desroy для верхней,которая в фокусе,Activate для имевшей фокус перед этим,дестрой для нее,затем активате для предыдущей,дестрой для нее и наконец дестрой для главной(почему-то без активате)
← →
Skyle © (2004-07-27 11:37) [12]Слежу за вашим обсуждением ибо недавно поимел подобный AV.
Только ситуация несколько иная..
Псевдокодprocedure TForm1.DoIt;
begin
with TForm2.Create(Self) do
try
ShowModal;
RefreshData; //Это метод TForm1
finally
Free;
end;
end;
Далееprocedure TForm1.RefreshData;
begin
if cds.Active then
cds.close;
cds.Params.ParamByName(......
.......
cds.Open;
end;
На TForm2 лежит несколько гридов, из них 2 доступны для редактирования. Напр. Editable1, Editable2. Остальные - R/O.
Отладчик дельфей:
В TForm2.OnDestroy;try
Editable1.Free;
except
ShowMessage("Editable1");
Raise;
end;
try
Editable2.Free;
except
ShowMessage("Editable2");
Raise;
end;
Сообщения выводятся только эти и бессистемно. Назависимо от видимости гридов или редактирования какого-либо. Была идея, что проблема в InplaceEditor, но как-то убедиться в этом не удалось...
MemProof выдаёт сообщение, что "удаление несуществующего" происходит примерно при таком CallStack
DoIt
RefreshData
cds.Open
..где-то унутре TClientDataSet, в различных местах.
Но при этом, если переписать TForm1.DoIt какwith TForm2.Create(Self) do
try
ShowModal;
RefreshData;
finally
try
Free;
except
ShowMessage("Here");
Raise;
end;
end;
сообщение "Here" мы получаем, а вот в случаеfinally
if ExceptObject <> nil then
ShowMessage("Before");
Free;
end;
не даёт сообщения "Before".
Т.о. вроде как AV и не наведённый...
Ничего не понимаю, но очень хочется разобраться...
← →
Manfred (2004-07-27 11:56) [13]To Skyle >А зачем вы гридам free делаете,почему не доверяете это дело форме владельцу?
← →
Skyle © (2004-07-27 12:25) [14]
> Manfred (27.07.04 11:56) [13]
Потому что удалось отладчиком получить AV в деструкторе WinControl, где удаляются все лежащие на нём контролы. Этот цикл был перенесён в деструктор формы, где уже без труда было вычленено 2 виновника. Также это помогло убедиться в том, что порядок уничтожения контролов не влияет на появление AV.
Я до этого не пользовался MemProof, и, по сути, связываю наши ситуации только на основании его показаний на место ошибки.
Всё остальное против того, что ошибка в cds.Open.
Особенно, если учесть, что
The error text is not generated by MemProof, but is retrieved from Windows by calling GetLastError. Unfortunatelly, some WinAPI functions do not set the LastError variable, even though the Win32 documentation says that they should.
Но вот только предыдущие сообщения об ошибке не внесли ясности...
Из-за того, что для получения AV в моём случае надо очень быстро махать мышкой и не всегда, тормознув в отладчике, его получаешь, была идея, что это работа какого-либо таймера. Да, на TForm2 есть таймер, но после выхода из ShowModal он не должен работать.
Реализация ShowModal при беглом её просмотре подсказывает мне, что WM_Timer там пролезть не должен. Как и всякие WM_Paint и иже с ними имеющиеся обработчики. То есть, есть мнение, что после выхода из ShowModal обработчики сообщений (WM_Timer, WM_PAINT конкретно) выполняться не должны. Я даже отключал всё, что можно - эффект тот же самый.
В общем, мне не удалось решить эту проблему и я просто надеюсь почерпнуть каких-либо идей из текущего обсуждения.
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2004.08.22;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.036 c