Форум: "Потрепаться";
Текущий архив: 2004.08.22;
Скачать: [xml.tar.bz2];
Внизпро Warning Найти похожие ветки
← →
Алхимик © (2004-08-03 17:22) [0]Загружаю из ресурса картинку и вставляю её в TImage.
Код:
procedure TfrmAbout.FormCreate(Sender: TObject);
var
jpg : TJpegImage;
res : TResourceStream;
begin
try
res := TResourceStream.CreateFromID(HInstance, 1, RT_RCDATA);
jpg := TJpegImage.Create;
jpg.LoadFromStream(res);
imgLogo.Picture.Assign(jpg);
finally
res.Free; // строка 101
jpg.Free; // строка 102
end;
end;
Делфи считает что res и jpg могут не быть инициализированы:
[Warning] About.pas(102): Variable "jpg" might not have been initialized
[Warning] About.pas(101): Variable "res" might not have been initialized
Почему?
← →
Алхимик © (2004-08-03 17:23) [1]Промахнулся. Надо бы в Основную. Ну да ладно.
← →
Sandman25 © (2004-08-03 17:24) [2]jpg := nil;
res := TResourceStream.CreateFromID(HInstance, 1, RT_RCDATA);
try
jpg := TJpegImage.Create;
jpg.LoadFromStream(res);
imgLogo.Picture.Assign(jpg);
finally
res.Free; // строка 101
jpg.Free; // строка 102
end;
← →
Johnmen © (2004-08-03 17:25) [3]Потому, как try :)
← →
Алхимик © (2004-08-03 17:29) [4]
> [2] Sandman25 © (03.08.04 17:24)
10x
← →
Sandman25 © (2004-08-03 17:31) [5][4] Алхимик © (03.08.04 17:29)
*%@!
← →
Алхимик © (2004-08-03 17:32) [6]
> [5] Sandman25 © (03.08.04 17:31)
Я в смысле "спасибо".
← →
Sandman25 © (2004-08-03 17:33) [7]Пожалуйста.
← →
Sandman25 © (2004-08-03 17:35) [8]Только сейчас понял, что это аналог 4u и пр. :)
← →
Sandman25 © (2004-08-03 17:35) [9]10x = tenx = tanks = танки
← →
Johnmen © (2004-08-03 17:43) [10]>Sandman25 © (03.08.04 17:35) [8]
Это не важно. Вот на вопрос не ответил - это факт :)
Алхимик, я думаю, не понял ещё "почему".
← →
Sandman25 © (2004-08-03 17:44) [11]
res := TResourceStream.CreateFromID(HInstance, 1, RT_RCDATA);
try
jpg := TJpegImage.Create;
try
jpg.LoadFromStream(res);
imgLogo.Picture.Assign(jpg);
finally
jpg.Free; // строка 102
end;
finally
res.Free; // строка 101
end;
Потому что локальные переменные не инициализируются? :)
← →
Sandman25 © (2004-08-03 17:47) [12]А вообще, конечно, потому что может быть ошибка при создании TJpegImage, и тогда вызовется Jpg.Free, хотя не должен.
← →
Val © (2004-08-03 17:51) [13]>[11] Sandman25 © (03.08.04 17:44)
а зачем еще один try? почему бы в первоначальном варианте попросту не вынести оба create перед try? Думаю об этом говорит и [3] Johnmen © (03.08.04 17:25).
← →
Sandman25 © (2004-08-03 17:54) [14][13] Val © (03.08.04 17:51)
Ошибку предлагаете - а если исключение при создании второго объекта? Первый уже не освободим...
Оптимально по быстродействию и в то же время абсолютно безопасно будет так:
r2 := nil;
r3 := nil;
...
rN := nil;
r1 := TR1.Create;
try
r2 := TR2.Create;
r3 := TR3.Create;
...
rN := TRN.Create;
..
finally
r1.Free;
r2.Free;
...
rN.Free;
end;
← →
Sergey Kaminski © (2004-08-03 17:55) [15]Доступно:
конструкторы должны вызываться ДО try. Если в try конструктор завершиться Exception, то переменная с ссылкой на объект будет содержать nil.
← →
Алхимик © (2004-08-03 17:56) [16][13] Val © (03.08.04 17:51)
Как я понимаю, самая "тонкая часть" - это оба create. Если вынести их за try, нафик этот try тогда нужен?
← →
Sandman25 © (2004-08-03 17:57) [17]>то переменная с ссылкой на объект будет содержать nil.
С чего Вы взяли? Что было, то и останется.
← →
Sergey Kaminski © (2004-08-03 17:58) [18]Sandman25 © (03.08.04 17:57) [17]
Пардон, именно это и имел в виду. Будет содержаться то, что было до вызова конструктора.
← →
Sergey Kaminski © (2004-08-03 17:58) [19]Sandman25 © (03.08.04 17:57) [17]
Пардон, именно это и имел в виду. Будет содержаться то, что было до вызова конструктора (might not have been initialized).
← →
Johnmen © (2004-08-03 17:59) [20]>Sandman25 © (03.08.04 17:54) [14]
Он не предлагал, а намекнул, что если вынести, то варнинга уже не будет...:)
А я намекал, что ни один криейт может быть не выполнен. А методы вызываются.
← →
Anatoly Podgoretsky © (2004-08-03 19:02) [21]Могут быть, и не дай боже если будут, огребешь еще и AV
← →
Алхимик © (2004-08-04 09:40) [22]Резюме:
Варнинги потому возникают, что локальные переменные не инициализируются.
И стоит присваивать им в начале NIL.
Верно?
← →
Думкин © (2004-08-04 09:44) [23]> [22] Алхимик © (04.08.04 09:40)
Нет стоит создавать до try который к finally относится.
← →
Sandman25 © (2004-08-04 09:48) [24][22] Алхимик © (04.08.04 09:40)
Не совсем. Даже с модульными переменными (которые инициализируются) могут быть проблемы:
var
Obj: TMyClass;
procedure Test;
begin
try
Obj := TMyClass.Create;
finally
Obj.Free;
end;
end;
begin
Test;
Test;
end.
Если при первом вызове Test объект был нормально создан и затем уничтожен, а при втором произошла ошибка в конструкторе, то произойдет попытка освобождения уже удаленного объекта, на который все еще указывает Obj после первого вызова Test. Нужно четко понимать, как работает finally, и писать правильный код: либо выносить Create за try, либо инициализировать nil"ом, либо вместо Free использовать FreeAndNil.
← →
Sandman25 © (2004-08-04 09:51) [25]либо выносить Create за try, либо инициализировать nil"ом, либо вместо Free использовать FreeAndNil
Не следует понимать, что любой из этих вариантов обеспечивает правильную работу. Все зависит от конкретного случая.
Если воспользоваться первым способом, то придется создавать вложенные try-finally, что не очень хорошо.
Второй способ работает всегда, но в простейшем случае работы с одним классом приводит к выполнению лишней операции.
Третий способ не имеет смысла для локальных переменных.
← →
Johnmen © (2004-08-04 09:59) [26]>Алхимик © (04.08.04 09:40) [22]
>Резюме:
>Варнинги потому возникают, что локальные переменные не инициализируются.
Не так. Потому, что МОГУТ БЫТЬ не проинициализированы.
>И стоит присваивать им в начале NIL.
>Верно?
Да.
← →
Sandman25 © (2004-08-04 10:00) [27][26] Johnmen © (04.08.04 09:59)
Локальные переменные могут быть проинициализированы компилятором?
← →
Johnmen © (2004-08-04 10:17) [28]>Sandman25 © (04.08.04 10:00) [27]
Вобщем да.
← →
Sandman25 © (2004-08-04 10:19) [29][28] Johnmen © (04.08.04 10:17)
Перед ними стоит var, после них нет =?
← →
Игорь Шевченко © (2004-08-04 10:23) [30]
> Локальные переменные могут быть проинициализированы компилятором?
Длинные строки, варианты и интерфейсы - да. Остальные - нет.
← →
Anatoly Podgoretsky © (2004-08-04 10:24) [31]Вобщем нет. Вот выписка
Global variables can be initialized at the same time they are declared
Локальные нет. Можно инициализировать локальные "константы"
← →
Johnmen © (2004-08-04 10:26) [32]Поэтому и сказал, вобщем. Т.е. по сути. Изменяемая константа.
const abc: <type> = <const>;
← →
Anatoly Podgoretsky © (2004-08-04 10:28) [33]Johnmen © (04.08.04 10:26) [32]
К тому моменту когда они изобрели эти "константы" они еже не дошли до идеи инициализированых переменных.
Но инициализировать на стадии компиляции и последующей загрузке, нельзя по простой причине, у локальных переменных нет явного адреса, они размещаются на стеке.
← →
Sandman25 © (2004-08-04 10:29) [34][32] Johnmen © (04.08.04 10:26)
Понятно. Переменная - это такая штука, перед которой const написано :)
← →
Anatoly Podgoretsky © (2004-08-04 10:34) [35]Sandman25 © (04.08.04 10:29) [34]
Ну да, весь мир Паскаля в свое время смеялся
Страницы: 1 вся ветка
Форум: "Потрепаться";
Текущий архив: 2004.08.22;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.032 c