Форум: "Основная";
Текущий архив: 2002.07.29;
Скачать: [xml.tar.bz2];
ВнизAccess Violation при закрытии программы. Найти похожие ветки
← →
Дельфятник (2002-07-15 10:52) [0]При закрытии программы закрываются окна, и когда программа пытается закрыть одно из окон, то возникают проблемы когда это окно в этот момент видимо - у этого окна по событию FormHide вызывается рисование картинки на главной форме. И выскакивает Access Violation. Я, конечно, поставил вызов перерисовки в try..except и пользователь не видит этой ошибки, но хотелось бы понять почему эта ошибка происходит. Сообщение такое:
Project prj.exe raised exception class EAccessViolation with message "Access violation at address 77F81B4D in module "ntdll.dll". Read of address 000003A0". Process stopped. Use Step or Run to Continue.
Я в отладчике нашёл строку, на которой выскакивает это сообщение. Выглядит она так:
canvas.brush.style:=bsSolid;
Чуть выше этой строки стоит with bm_w do begin, то есть Canvas относится к bm_w типа TBitmap. При этом я проверял
bm_w=nil - возвращает False,
Bm_w.Canvas=nil - возвращает False,
Bm_w.Canvas.Brush=nil - возвращает False,
Bm_w.Canvas.Brush.Style=nil - возвращает False.
В чём может быть дело?
← →
Digitman (2002-07-15 12:36) [1]>>Bm_w.Canvas.Brush.Style=nil - возвращает False.
А вот это - нонсенс. Св-во Style не указательного типа, это - св-во типо "перечисление"
← →
AL2002 (2002-07-15 13:05) [2]try..except — и всё нормально.
canvas.brush.style:=bsSolid;
Получается, на этой строчке ошибка?
То выкинь её.
← →
valery_f (2002-07-15 13:22) [3]> Дельфятник (15.07.02 10:52) ...При закрытии программы...
Похоже одна форма пытается обратиться ко второй, когда она уже убита (убита, а указатель остался прежним и проверка на nil, ессно, ничего не даст).
Если я правильно тебя понял, то, так чтоб по простому, - предположим Form1 - главная, а Form2 - пытается рисовать в главной при OnHide:
procedure TForm1.FormDestroy(Sender: TObject);
begin
Form1 := nil;
end;
procedure TForm2.FormHide(Sender: TObject);
begin
//а может Form1 уже не существует?
if Form1 <> nil then begin
//рисуем
Form1.Canvas...
...
end;
end;
← →
Дельфятник (2002-07-15 15:05) [4]Для valery_f:
У меня главная форма называется fm_main, и, соответственно:
procedure TFm_main.FormDestroy(Sender: TObject);
begin
fm_main:=nil
end;
procedure TForm2.FormHide(Sender: TObject);
begin
try
if (fm_main<>nil) and fm_main.Visible then // вызов перерисовки
except
end
end;
Не помогло. Причём если сначала закрыть Form2 (вручную), а затем программу, то всё нормально. Но я же не могу этого требовать от пользователя.
← →
valery_f (2002-07-15 15:20) [5]2 Дельфятник
Мыльни исходник, посмотрим.
← →
Дельфятник (2002-07-15 16:40) [6]А к исходнику нужна база ~700Мб.
← →
valery_f (2002-07-15 17:00) [7]> А к исходнику нужна база ~700Мб
Как все плохо... Если отрисовка (с возникающим AV) не связана с базой - можно скопировать проект и выкинуть базу, а если так уж сильно связана - можно в таблицах оставить 1-2 демо-записи, и будет это - считанные килобайты...
Покажи хотя-бы полный текст перерисовки в TForm2.FormHide и поясни как обе формы связаны.
← →
Дельфятник (2002-07-15 17:58) [8]Отрисовка связана с базой - рисуются данные из базы. Кроме того база - это более 75 таблиц.
А формы связаны так - на главной форме рисуются данные из Form2 когда Form2 видима и не рисуются когда Form2 невидима. Поэтому по закрытию Form2 надо перерисовывать картинку.
Перерисовка начинается так:
begin
obj_priz_ris;
with bm_w do
begin
width:=Fm_main.width;
height:=Fm_main.height;
pen_width:=fm_main.Im1.Canvas.Pen.Width;
pen_color:=fm_main.Im1.Canvas.Pen.color;
brush_Color:=fm_main.Im1.Canvas.brush.Color;
pen_Style:=fm_main.Im1.Canvas.Pen.style;
canvas.brush.style:= bsSolid; // здесь как раз и выскакивает AV
ну и дальше прорисовка всякая
Im1: TImage - на нём всё и рисуется - сначала рисуется на bm_w, а потом в конце перерисовки bm_w копируется на fm_main.Im1:
fm_main.Im1.Canvas.draw(0,0,bm_w)
← →
BAY (2002-07-15 18:03) [9]>Дельфятник
А пробовол запускать не под Дельфей, а напрямую exe-шник?
← →
Дельфтник (2002-07-15 18:05) [10]Ну я ж написал, что я try..except поставил, и в результате пользователь никакого AV не видит. Соответственно, если запустить exe, то никакой ошибки не будет. Но вопрос в том, как избавиться от этой ошибки по-нормальному, а не через try..except.
← →
BAY (2002-07-15 18:10) [11]>Дельфтник
Я имею ввиду без try..except
← →
Дельфятник (2002-07-15 18:16) [12]2 BAY: Да, всё равно выскакивает.
← →
Дельфятник (2002-07-16 09:48) [13]Кстати, я тут посмотрел что событие Form2.OnHide обрабатывается раньше, чем Fm_main.FormDestroy. Поэтому-то и не помог первый совет Валерия (valery_f (15.07.02 13:22)).
← →
valery_f (2002-07-16 11:45) [14]> Дельфятник (15.07.02 17:58) ...на главной форме рисуются данные из Form2 когда Form2 видима... по закрытию Form2 надо перерисовывать картинку...
Ты хочешь сказать, что код отрисовки главной формы впаян в другую форму? Это не очень-то красиво. Каждая форма должна САМА рисовать все, что ей нужно, прочие варианты потенциально глюкавы, и, по большей части, именно в такие моменты - создание и уничтожение форм. Старайся избавляться от перекрестных ссылок и связей, а то это уже не только не ООП, но даже и не модульное программирование...
В твоем примере пока не все ясно. Для начала - кому "принадлежит" bm_w? Когда bm_w создается и когда уничтожается? Может - на момент OnHide битмапа ужет нет?
Давай так. Глянь - жив ли bm_w в момент глюка (сдается мне что таки нет), если все в порядке - замыль мне DFM и PAS для главного окна и для второй формы.
← →
Дельфятник (2002-07-17 13:53) [15]Точно. По TFm_main.FormClose происходило bm_w.Free и обнуление массивов, из которых рисовались данные на картинке. А TFm_main.FormClose происходило до Form2.FormHide и, соответственно, выскакивала ошибка. Я закомментировал эти обнуления в TFm_main.FormClose и всё стало нормально.
Большое спасибо!
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2002.07.29;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.006 c