Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 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
1-1091484317
denkop
2004-08-03 02:05
2004.08.22
"Правильное" завершение работы программы


14-1091658588
Soft
2004-08-05 02:29
2004.08.22
Страна Советия.


1-1091805745
ghg
2004-08-06 19:22
2004.08.22
размер стека


3-1090582091
karat
2004-07-23 15:28
2004.08.22
Запрос к FireBird. Не хватает памяти.


3-1090936502
AlexanderSK
2004-07-27 17:55
2004.08.22
Разрыв коннекта с БД





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский