Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.06.27;
Скачать: CL | DM;

Вниз

Плавающее Access Violation   Найти похожие ветки 

 
Andrey007   (2004-06-09 09:45) [0]

У меня Access Violation выскакивал при выполнении следующего куска кода.
if (Areas<>nil) and (Areas.Count>0) then for i:=0 to Areas.Count-1 do
try
 if (TVRTimes(Areas.Items[i]).times<>nil) and (TVRTimes(Areas.Items[i]).times.Count>0) then
// вот на этом if как раз и выскакивал Access Violation
 for j:=0 to TArea(Areas.Items[i]).times.Count-1 do
 begin
   if TVRTime(TVRTimes(Areas.Items[i]).times[j]).beg<beg
   then beg:=TVRTime(TVRTimes(Areas.Items[i]).times[j]).beg;
   if TVRTime(TVRTimes(Areas.Items[i]).times[j]).en>en
   then en:=TVRTime(TVRTimes(Areas.Items[i]).times[j]).en
 end;
except
end;

Эта процедура у меня стоит в методе класса. Я проверял правильность преобразования типов - всё правильно, выход за границы списка - ошибка вываливалась на первом же элементе списка (в смысле, на элементе списка с номером ноль).
В отладчике по Ctrl+F7 когда проверяю TVRTimes(Areas.Items[i]).times=nil, выдавался результат - False, а когда хотел посмотреть TVRTimes(Areas.Items[i]).times.Count, то выдвалось DelphiException. То же самое и когда хотел посмотреть TVRTimes(Areas.Items[i]).times.ClassName. (Этот times на самом деле TObjectList)
Ничего так и не надумал, решил заняться этим на следующий день. А сегодня всё работает нормально. У кого так было? В чём может быть дело?


 
Тимохов ©   (2004-06-09 09:46) [1]

значит какой-то items[i] равен nil


 
Тимохов ©   (2004-06-09 09:48) [2]

за except end убивать надо...


 
Polevi ©   (2004-06-09 09:48) [3]

Assigned(Areas.Items[i]) ?


 
Anatoly Podgoretsky ©   (2004-06-09 09:52) [4]

Вот это может дать ошибку в зависимости от настроек
if (Areas<>nil) and (Areas.Count>0) then for i:=0 to Areas.Count-1 do
Можно написать так
if (Areas<>nil) then for i:=0 to Areas.Count-1 do
И в других местах аналогично


 
Danilka ©   (2004-06-09 09:54) [5]

procedure TForm1.Button1Click(Sender: TObject);
var
 sl: TStringList;
begin
 sl:=TStringList.Create;
 sl.Free;
 if Assigned(sl) then ShowMessage("Assigned");
 if sl <> nil then ShowMessage("not nil");
 ShowMessage(IntToStr(sl.Count)); // получим по-башке
end;


 
Danilka ©   (2004-06-09 09:56) [6]

Это я вот к этому:

> TVRTimes(Areas.Items[i]).times=nil, выдавался результат
> - False, а когда хотел посмотреть TVRTimes(Areas.Items[i]).times.Count,
> то выдвалось DelphiException


 
panov ©   (2004-06-09 09:59) [7]

>Тимохов ©   (09.06.04 09:48) [2]

за except end убивать надо...

Неправда. Это нормальная ситуация - подавление Exception.


 
Тимохов ©   (2004-06-09 10:02) [8]


> panov ©   (09.06.04 09:59) [7]

надо не давать, а обрабатывать...
имхо конечно, но думаю, многие согласятся...


 
Тимохов ©   (2004-06-09 10:04) [9]


> panov ©   (09.06.04 09:59) [7]

вернее так - давить исключения можно, но не все же.
AV точно нельзя давить, т.к. это может привести к совершенно жутким последствиям...


 
vecna ©   (2004-06-09 10:51) [10]

согласен с Тимохов,

(TVRTimes(Areas.Items[i]).times.Count>0)

Assigned(times) ?


 
Andrey007   (2004-06-09 10:57) [11]

> Тимохов ©
> значит какой-то items[i] равен nil

Как может быть Areas.Items[i] равен nil если TVRTimes(Areas.Items[i]).times не равен nil?

> за except end убивать надо...

Если Вы посмотрите исходники VCL, то увидите там except end не раз и не два.

> Anatoly Podgoretsky ©   (09.06.04 09:52) [4]
> Вот это может дать ошибку в зависимости от настроек

А какие настройки Вы имеете в виду?


 
KSergey ©   (2004-06-09 10:58) [12]

> [7] panov ©   (09.06.04 09:59)
> Неправда. Это нормальная ситуация - подавление Exception.

Что-то я вас не понял, в контексте вопроса...


 
KSergey ©   (2004-06-09 10:59) [13]

> [11] Andrey007   (09.06.04 10:57)

> А какие настройки Вы имеете в виду?

Вероятно эти:
{$B-}
{$B+}
Ну или соотв. опции проекта


 
KSergey ©   (2004-06-09 11:01) [14]

> [11] Andrey007   (09.06.04 10:57)
> Если Вы посмотрите исходники VCL, то увидите там except
> end не раз и не два.

Да, но если бы узнать мотивы, двигавшие вами в написании этого - можно было бы скаать правомочно это или нет в данном случае. И есть у меня нехорошие подозрения, что... см. [9] Тимохов ©   (09.06.04 10:04)


 
Andrey007   (2004-06-09 11:04) [15]

Я заменил begin ... end на try ... except end после того, как стало выскакивать Access Violation.


 
Тимохов ©   (2004-06-09 11:04) [16]


> Andrey007   (09.06.04 10:57) [11]
> > Тимохов ©

> Как может быть Areas.Items[i] равен nil если TVRTimes(Areas.Items[i]).times
> не равен nil?

запросто.


 
Тимохов ©   (2004-06-09 11:05) [17]


> Andrey007   (09.06.04 11:04) [15]
> Я заменил begin ... end на try ... except end после того,
> как стало выскакивать Access Violation.

браво.
решение достойное королей софтверного бизнеса...

:)))


 
Игорь Шевченко ©   (2004-06-09 11:06) [18]

panov ©   (09.06.04 09:59)


> Неправда. Это нормальная ситуация - подавление Exception.


Ничего, кроме головной боли, это подавление не приносит.

Тимохов ©   (09.06.04 09:48) [2] абсолютно прав.


 
Danilka ©   (2004-06-09 11:06) [19]

[10] vecna ©   (09.06.04 10:51)
Я привел пример, когда Assigned будет возвращать true, когда ссылка будет не равна nil, и при этом самого объекта уже не будет.
Скорее всего, этот вариант и имел место быть - объект создали, затем прибили, а ссылку не обнулили.


 
Тимохов ©   (2004-06-09 11:08) [20]


> Andrey007   (09.06.04 10:57) [11]


> Как может быть Areas.Items[i] равен nil если TVRTimes(Areas.Items[i]).times
> не равен nil?
>
> > за except end убивать надо...

еще вариант (как пишет Danilka) - не равен nil, но указывает на давно (или недавно) удаленный объект, т.е. указывает фиг знает куда... иногда это будет работать, иногода нет. поэтому и нерегулярность возникновения ошибки.


 
Andrey007   (2004-06-09 11:12) [21]

> Danilka ©
> Скорее всего, этот вариант и имел место быть - объект создали, затем прибили, а ссылку не обнулили.

Прикол в том, что этот код вызывается из FormCreate формы, которая создаётся при запуске программы. То есть это первое исполнение этого кода - проверял, устанавливая там точку останова перед запуском программы.


 
Anatoly Podgoretsky ©   (2004-06-09 11:14) [22]

В контексте вопроса, если бы тихо не было подавлено исключение, то возможно было бы осмысленное сообщение и возможно на более ранней стадии не доходя до AV


 
Danilka ©   (2004-06-09 11:20) [23]


> Прикол в том, что этот код вызывается из FormCreate формы

Да хоть где.
Откуда-то берется и сам Areas, и его итемсы. Если они создаются здесь-же, в этой-же процедуре, и не прибиваются до этого кода, то и смыла нет проверять их на то, созданы они или нет, равны ли nil или нет.


 
Andrey007   (2004-06-09 11:27) [24]

> Anatoly Podgoretsky ©   (09.06.04 11:14) [22]

> В контексте вопроса, если бы тихо не было подавлено исключение, то возможно было бы осмысленное сообщение и возможно на более ранней стадии не доходя до AV

Дело в том, что AV выскакивало при запуске программы из Delphi и никаких предшествующих сообщений не было. В отладчике у меня стоит галка "Stop on Delphi Exceptions".

> Danilka ©   (09.06.04 11:20) [23]

> Да хоть где.
> Откуда-то берется и сам Areas, и его итемсы. Если они создаются здесь-же, в этой-же процедуре, и не прибиваются до этого кода, то и смыла нет проверять их на то, созданы они или нет, равны ли nil или нет.

Сначала создаётся Areas (TObjectList), потом элементы, которыми он наполняются, потом эти элементы заталкиваются в него, и потом вызывается обсуждаемый кусок кода.


 
Тимохов ©   (2004-06-09 11:30) [25]


> Andrey007   (09.06.04 11:27) [24]

чую вы дозреваете потихонечку до мысли, что так вам никто ничего дельного не скажет и что нужно бы больше кода привести.


 
Danilka ©   (2004-06-09 11:32) [26]

[24] Andrey007   (09.06.04 11:27)
Тогда какой смысл вообще проверять: Areas<>nil, если он здесь-же создается?
И какой смысл проверять элементы?
Если проверяешь, значит есть вероятность, что объекты больше не существуют, так?


 
BzionWar   (2004-06-09 11:34) [27]

Все таки попробуйте
Anatoly Podgoretsky ©   (09.06.04 09:52) [4]
У меня как-то раз был почти такой же случай. Помогло именно то, что посоветовал АП.
Точнее, я разделил условие проверки на nil и следующее сравнение.


 
Mystic ©   (2004-06-09 12:49) [28]


> надо не давать, а обрабатывать...
> имхо конечно, но думаю, многие согласятся...


Если нужно подавить исключение, я использую вместо try except end конструкцию:

try
except
 on E: EAbotCalculation do;
end;


 
Тимохов ©   (2004-06-09 12:56) [29]


> Mystic ©   (09.06.04 12:49) [28]

во, именно это я и имею в виду - подавлять надо только то, что вы своим разумом знаете подавлять надо и можете точно объяснить зачем это нужно делать. Подавать все - непростительно...


 
Andrey007   (2004-06-09 13:18) [30]

> Danilka ©   (09.06.04 11:32) [26]
> Тогда какой смысл вообще проверять: Areas<>nil, если он здесь-же создается?

В том классе, у которого есть это свойство, Areas может быть равен nil. Я не совсем правильно выразился в прошлый раз - тогда я имел в виду конкретную ситуацию, когда Areas всё-таки создавался. А в принципе он может и не создаваться. Тогда он nil.

> И какой смысл проверять элементы?
> Если проверяешь, значит есть вероятность, что объекты больше не существуют, так?

Да. Если бы ошибка не выскакивала, я бы и не ставил проверки.

В общем, тот кусок я переделал вот так:

 if (Areas<>nil) and (Areas.Count>0) then for i:=0 to Areas.Count-1 do
 if (Areas.Items[i]<>nil) and (TVRTimes(Areas.Items[i]).times<>nil) and
     Assigned(TVRTimes(Areas.Items[i]).times) and
    (TVRTimes(Areas.Items[i]).times.Count>0) then
 for j:=0 to TArea(Areas.Items[i]).times.Count-1 do
 begin
   if TVRTime(TVRTimes(Areas.Items[i]).times[j]).beg<beg
   then beg:=TVRTime(TVRTimes(Areas.Items[i]).times[j]).beg;
   if TVRTime(TVRTimes(Areas.Items[i]).times[j]).en>en
   then en:=TVRTime(TVRTimes(Areas.Items[i]).times[j]).en
 end;

При этом в опциях компилятора у меня не стоит галка "Complete boolean eval", а в проекте директивы {$B+} нигде нет.


 
KSergey ©   (2004-06-09 13:24) [31]

>  А в принципе он может и не создаваться. Тогда он nil.

А уверенность в этом есть? ЧТо он именно nil, если не создался??

> [15] Andrey007   (09.06.04 11:04)
> Я заменил begin ... end на try ... except end после того,
> как стало выскакивать Access Violation.

Вот это я и подозревал... и не я один...

Но как же хочется услышать начальника транспортного цеха!


 
Anatoly Podgoretsky ©   (2004-06-09 13:28) [32]

Дело даже не в директива, при нулевой длине будет for I := 0 to -1 и цикл точно также не будет исполняться, но зато не будет возможности для ошибки при разном вычислении выражения.
Кроме того не гарантируется порядок вычисления, дело компилятора. Но в случае не полного вычисления слева направо с учетом приоритетов.


 
Andrey007   (2004-06-09 13:28) [33]

> KSergey ©   (09.06.04 13:24) [31]

> А уверенность в этом есть? ЧТо он именно nil, если не создался??

Вот конструктор того класса, которому принадлежит Areas:

constructor TVR.Create;
begin
 inherited Create;
 Areas:=nil;
// и прочая
...
end;



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

Текущий архив: 2004.06.27;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.033 c
8-1081715003
Gott
2004-04-12 00:23
2004.06.27
Звукозапись


3-1086014082
Temucin
2004-05-31 18:34
2004.06.27
оракл+делфи


8-1081841509
Max003
2004-04-13 11:31
2004.06.27
Как узнать установлен-ли FLASH player для веб броузера?


1-1086976623
Morrison
2004-06-11 21:57
2004.06.27
Как реализовать в Delphi аналог процедуры read?


3-1086239467
Inkotex
2004-06-03 09:11
2004.06.27
IBDataBase