Форум: "Начинающим";
Текущий архив: 2012.06.03;
Скачать: [xml.tar.bz2];
Внизtry .. finally внутри try .. except Найти похожие ветки
← →
Nucer (2012-01-24 16:22) [0]Код:
procedure MyProc;
begin
try
...
Obj := TObj.Create;
try
...
Value := ...;
...
finally
Obj.Free;
end;
if Value then ...;
...
except
...
end;
end;
Delphi 7 предупреждает об ошибке:
[Warning] Unit1.pas(438): Variable "Value" might not have been initialized
Ошибка среды? Или я что-то делаю не так?
← →
MBo © (2012-01-24 16:27) [1]Это не ошибка, а предупреждение, ведь Value действительно не всегда будет присвоено значение.
← →
Nucer (2012-01-24 16:30) [2]Но ведь если значение не будет присвоено, то и до проверки значения дело не дойдет?
← →
sniknik © (2012-01-24 16:35) [3]глобальная переменная... откуда знать что после этой процедуры другая ее не использует?
← →
Nucer (2012-01-24 16:38) [4]Прошу прощения за неточность(по примеру кода этого не видно), но переменная локальная.
← →
Nucer (2012-01-24 16:42) [5]Вот реальный пример (можно скопировать в IDE и увидеть предупреждение):
procedure Test;
var
Obj: TStringList;
Value: Integer;
begin
try
Obj := TStringList.Create;
try
if Random(10) = 0 then raise Exception.Create("Error!");
Value := Obj.Count;
finally
Obj.Free;
end;
if Value > 0 then Sleep(1000);
except
MessageBox(0, "Error!", "Error!", 0);
end;
end;
← →
Ega23 © (2012-01-24 16:46) [6]
> Вот реальный пример (можно скопировать в IDE и увидеть предупреждение):
Буратино дали 3 яблока. 2 яблока он съел. Сколько яблок осталось у Буратино?
← →
Nucer (2012-01-24 16:51) [7]
> Буратино дали 3 яблока. 2 яблока он съел. Сколько яблок
> осталось у Буратино?
Одно, но я не вижу связи. Если бы мне была известна причина появления warning"a, то я бе не создавал тему на форуме. С моей точки зрения в коде отсутствует неопределеннность.
← →
Ega23 © (2012-01-24 16:53) [8]
> Одно, но я не вижу связи.
Не одно, а неизвестно. Ибо неизвестно, сколько яблок было у Буратино до того, как ему дали 3.
Посему - инициализируй локальные переменные, без неоднозначностей.
Поставь в самом начале Value := 0.
← →
Dimka Maslov © (2012-01-24 17:00) [9]Компилятору формально по барабану. Он видит, что инициализация переменной происходит внутри блока (неважно какого блока иф или трю), а использование - вне этого блока. Вот и ругается.
← →
Nucer (2012-01-24 17:03) [10]Добавление в начало "Value := 0" избавит от сообщения, но по сути как раз это и будет ошибкой ("Value assigned to "Value" never used"). Если я не прав, то в каком месте этот 0 теоритически может быть использован?
← →
Nucer (2012-01-24 17:04) [11]
> Dimka Maslov © (24.01.12 17:00) [9]
Т. е., грубо говоря, данное предупреждение является ложным?
← →
Ega23 © (2012-01-24 17:09) [12]
> Т. е., грубо говоря, данное предупреждение является ложным?
1. Локальные переменные не инициализируются.
2. Компилятор не такой умный, как тебе кажется.
3. Если он видит, что "теоретически неинициализированная переменная" может быть использована - он честно тебя предупреждает.
4. В твоём конкретном случае Value вообще не нужна. Перенеси if внутрь try:procedure Test;
var
Obj: TStringList;
begin
try
Obj := TStringList.Create;
try
if Random(10) = 0 then raise Exception.Create("Error!");
if Obj.Count > 0 then Sleep(1000);
finally
Obj.Free;
end;
except
MessageBox(0, "Error!", "Error!", 0);
end;
end;
← →
Dimka Maslov © (2012-01-24 17:20) [13]За прошедший год это уже вторая ветка на ту же тему. Решение одно - явно инициализируй переменные. Это не будет ошибкой, а строки с value assigned never used в объектный код не попадают. Если уж очень не хочется, сделай себе функцийю
procedure Hole(var V);
asm
ret
end;
и вызывай её вместо Value := 0, тогда ругаццо не будет.
← →
Anatoly Podgoretsky © (2012-01-24 17:32) [14]> Ega23 (24.01.2012 16:46:06) [6]
А чьи яблоки он съел?
← →
_Юрий (2012-01-25 19:59) [15]
> Nucer (24.01.12 17:04) [11]
> Т. е., грубо говоря, данное предупреждение является ложным?
Да
← →
Anatoly Podgoretsky © (2012-01-25 20:51) [16]Предупреждение правильное, не ложное.
← →
RWolf © (2012-01-26 01:56) [17]
> [16]
при каком стечении обстоятельств в приведённом коде переменная Value не будет инициализирована к моменту проверки её значения?
← →
Он же Самуилыч (2012-01-26 02:03) [18]Господа, не стоит требовать от компилятора слишком многого. Слава Богу, он еще не искуственный интеллект, иначе работать с ним было бы совсем невозможно.
Даже и люди-то далеко не все интеллектом блещут... так чего же вы от программы хотите?
← →
Inovet © (2012-01-26 02:04) [19]> [17] RWolf © (26.01.12 01:56)
При исключении там, где первое многоточие.
← →
Он же Самуилыч (2012-01-26 02:07) [20]
> Inovet © (26.01.12 02:04) [19]
Не, дружище, тут ты неправ. Там весь код взят в try-except, поэтому компилятор, будь он умным, вообще не должен выдавать никаких ворнингов. Но он всего лишь компилятор...
← →
Inovet © (2012-01-26 02:17) [21]> [20] Он же Самуилыч (26.01.12 02:07)
> Не, дружище, тут ты неправ.
Во втором многоточии т.е.. При исключении отработает
Obj.Free;
потом
if Value then ...;
А она не инициализирована. Нет разве?
← →
Anatoly Podgoretsky © (2012-01-26 08:42) [22]
> при каком стечении обстоятельств в приведённом коде переменная
> Value не будет инициализирована к моменту проверки её значения?
>
При любом исключение до присвоения, а поскольку у тебя два ряда точек, то мест очень много.
← →
RWolf © (2012-01-26 09:25) [23]
> Inovet © (26.01.12 02:17) [21]
> Во втором многоточии т.е.. При исключении отработает Obj.Free;
> потом if Value then ...;А она не инициализирована. Нет разве?
Исключение во втором многоточии приведёт к завершению выполнения процедуры из-за исключения сразу же после Obj.Free, до проверки условия управление не дойдёт.
← →
RWolf © (2012-01-26 09:26) [24]т.е. управление провалится сразу в except-секцию.
← →
Inovet © (2012-01-26 11:29) [25]> [24] RWolf © (26.01.12 09:26)
> т.е. управление провалится сразу в except-секцию.
Да.
← →
_Юрий (2012-01-26 20:17) [26]
> Он же Самуилыч (26.01.12 02:07) [20]
> Не, дружище, тут ты неправ. Там весь код взят в try-except,
> поэтому компилятор, будь он умным, вообще не должен выдавать
> никаких ворнингов. Но он всего лишь компилятор...
Нет, дружище, тут ты не прав. Внешний try-except тут вообще ни при чем, его можно было бы исключить из модели как лишнюю сущность.
Потому, что управление не попадет на строчку "if Value then ...;" в случае возникновения исключения выше независимо от того, есть этот внешний блок, или его нету.
Если же ты считаешь, что внутри try-except вообще не должно быть варнингов потому, что потом идет exept, то тут ты опять не прав.
Обязательно должны быть. Напомню, что у нас в VCL-Forms вообще все обработчики сообщений по умолчанию стоят внутри глобального try-except (отлов исключений на уровне Application). А также все запуски в потоке потомков TThread тоже, то есть практически весь код приложения, кроме инициализации и финализации.
Так что тут компилятор выступил нормально. Ненормально он выступил с этим ложным варнингом.
Кстати, в C# обращение к неинициализированной переменной в силу управляемости кода вообще приводит к ошибке компиляции, а не к варнингу. И там подобных косяков нет - все работает четко. Я уж не знаю, почему у них получилось, а у нас нет.
А тут приходится ставить лишнюю инициализацию, что по сути является ошибкой. Лишние операции процессора - пусть мелочь, но принципиально они лишние. И тем не менее, приходится так делать, потому что это меньшее зло, чем оставлять варнинг, или чем отключать варнинги на участке кода - тогда можно пропустить реальную опасность
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2012.06.03;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.004 c