Форум: "Начинающим";
Текущий архив: 2008.06.08;
Скачать: [xml.tar.bz2];
ВнизОсвобождение ресурса в finally Найти похожие ветки
← →
Arinyshka (2008-04-23 12:17) [0]Не подскажете еще один момент:
Есть процедура, выглядит примерно так
procedure TSetPayFrm.BtnAddImageClick(Sender: TObject);
var TempBitmap:TBitmap;
begin
if not(opendialog1.Execute) then exit;
try
TempBitmap := TBitmap.Create;
TempBitmap.LoadFromFile(OpenDialog1.FileName);
finally
TempBitmap.Free;
end;
end;
На освобождение TempBitmap.Free; выдает варнинг
[Warning] uSetPaymentMain.pas(313): Variable "TempBitmap" might not have been initialized
Не смертельно, но непонятно... почему варнинг? При изменениии условия и включении всей конструкции в один блок begin..end ситуация не менялась.
← →
Рамиль © (2008-04-23 12:18) [1]
TempBitmap := TBitmap.Create;
try
TempBitmap.LoadFromFile(OpenDialog1.FileName);
finally
TempBitmap.Free;
end;
← →
Arinyshka (2008-04-23 12:21) [2]упс :) чувствую себя дура дурой :) Ну конечно! спасибо :)))))
← →
Ega23 © (2008-04-23 12:21) [3]
> Не смертельно, но непонятно... почему варнинг?
Потому что если в конструкторе произойдёт исключение, то TempBitmap будет равен nil. А после ты попадаешь на finally, где вызываешь free.
Create нужно выносить за блок try..finally
← →
{RASkov} © (2008-04-23 12:22) [4]> но непонятно... почему варнинг?
Потому как создание объекта в защищенной секции, а уничтожение принудительное в финале.... поэтому компилятор и говорит, что объект может и не создасться и в финале будет АВ.
Решение в [1]... т.е. создание вынести из защитного блока...
← →
{RASkov} © (2008-04-23 12:22) [5]:)
← →
{RASkov} © (2008-04-23 12:23) [6]> Потому что если в конструкторе произойдёт исключение, то
> TempBitmap будет равен nil. А после ты попадаешь на finally,
> где вызываешь free.
Если в конструкторе будет ошибка то в секцию финал мы не попадем вовсе...
← →
{RASkov} © (2008-04-23 12:24) [7]> [6] {RASkov} © (23.04.08 12:23)
.... это если использовать код из [1]
← →
Palladin © (2008-04-23 12:25) [8]
> Ega23 © (23.04.08 12:21) [3]
> то TempBitmap будет равен nil. А после ты попадаешь на finally,
> где вызываешь free.
ха... если бы он был равен Nil.. он не равен Nil, Nil для Free несмертелен, TempBitmap будет неинициализирован то бишь мусор, а вот это для Free уже критично
← →
Ega23 © (2008-04-23 12:30) [9]
> Если в конструкторе будет ошибка то в секцию финал мы не
> попадем вовсе...
>
Да ну????
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TMyObj = class
public
constructor Create(const RaiseException : Boolean = False);
procedure DoWork;
end;
TForm2 = class(TForm)
Button1: TButton;
Label1: TLabel;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
{ TMyObj }
constructor TMyObj.Create(const RaiseException: Boolean);
begin
if RaiseException then
raise Exception.Create("TMyObj.Create");
end;
procedure TMyObj.DoWork;
begin
ShowMessage("TMyObj.DoWork");
end;
procedure TForm2.Button1Click(Sender: TObject);
var
obj : TMyObj;
begin
Label1.Caption := "";
obj := TMyObj.Create(True);
try
obj.DoWork;
finally
Label1.Caption := "попали в finally";
obj.Free;
end;
end;
procedure TForm2.Button2Click(Sender: TObject);
var
obj : TMyObj;
begin
Label1.Caption := "";
try
obj := TMyObj.Create(True);
obj.DoWork;
finally
Label1.Caption := "попали в finally";
obj.Free;
end;
end;
end.
← →
Ega23 © (2008-04-23 12:32) [10]
> ха... если бы он был равен Nil.. он не равен Nil, Nil для
> Free несмертелен, TempBitmap будет неинициализирован то
> бишь мусор, а вот это для Free уже критично
>
Согласен, неточно выразился.
← →
Рамиль © (2008-04-23 12:34) [11]
> Ega23 © (23.04.08 12:32) [10]
Сам попался? :)
← →
Anatoly Podgoretsky © (2008-04-23 12:36) [12]> Arinyshka (23.04.2008 12:17:00) [0]
Правильно говорит, код из Вредных Заветов
Создание должно быть до try
← →
Ega23 © (2008-04-23 12:36) [13]
> Сам попался? :)
С некоторых пор, если есть вероятность того, что в конструкторе raise встретится, предпочитаю сначала nil приравнять... :)
← →
Anatoly Podgoretsky © (2008-04-23 12:38) [14]
> Потому что если в конструкторе произойдёт исключение, то
> TempBitmap будет равен nil.
Это ты погорячился, переменная то локальная, а субъект не является субъектом с регулируемым сроком жизни.
← →
{RASkov} © (2008-04-23 12:42) [15]> [9] Ega23 © (23.04.08 12:30)
А вот такой вариант:function CrBut: TButton;
begin
Result:=TButton.Create(nil);
Result.Tag:=Random(15);
Result.Caption:=IntToStr(Result.Tag);
if Result.Tag<7 then begin
raise Exception.Create("Error in constructor");
Result.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var B: TButton;
begin
Randomize;
B:=CrBut;
try
B.Parent:=Self;
B.Caption:=B.Caption+" Ok";
ShowMessage("B Ok");
finally
B.Free;
ShowMessage("Finally");
end;
end;
← →
ANB (2008-04-23 12:44) [16]
> TempBitmap := TBitmap.Create;
> try
> TempBitmap.LoadFromFile(OpenDialog1.FileName);
> finally
> TempBitmap.Free;
> end;
TempBitmap := nil;
try
TempBitmap := TBitmap.Create;
TempBitmap.LoadFromFile(OpenDialog1.FileName);
finally
TempBitmap.Free;
end;
Это классика. Позволяет избежать дублирования финалли, если объектов много, при этом все корректно отработает.
← →
{RASkov} © (2008-04-23 12:47) [17]> [9] Ega23 © (23.04.08 12:30)
> Button2Click
В этом случае мы попадаем в финал так как коструктор тоже в защитном блоке...
← →
Leonid Troyanovsky © (2008-04-23 13:12) [18]
> ANB (23.04.08 12:44) [16]
> Это классика.
Это заблуждение.
Исключения конструктора следует передавать обработчику
следующего уровня.
А защищать ресурсы в этом случае не нужно - деструктор
вызовется автоматом.
--
Regards, LVT.
← →
{RASkov} © (2008-04-23 13:15) [19]> [16] ANB (23.04.08 12:44)
> TempBitmap := nil;
> try
> TempBitmap := TBitmap.Create;
> TempBitmap.LoadFromFile(OpenDialog1.FileName);
> finally
> TempBitmap.Free;
> end;
>
> Это классика.
А по мне, мне кажется [1] более роднее и вернее.... [16] и выглядит как-то подозрительно...
А если после возникновения ошибки в конструкторе, он(конструктор) вернет не рыбу не мясо... т.е. не nil и не объект...
Я правда трудно себе это представляю, но.... в финале АВ :)
← →
Плохиш © (2008-04-23 13:19) [20]
> А если после возникновения ошибки в конструкторе, он(конструктор)
> вернет не рыбу не мясо... т.е. не nil и не объект...
При возникновении исключения в конструкторе, операция присваивания не будет выполнена.
← →
{RASkov} © (2008-04-23 13:20) [21]> [20] Плохиш © (23.04.08 13:19)
> При возникновении исключения в конструкторе, операция присваивания
> не будет выполнена.
:)
Ну да... тоже верно... Но все равно [1] мне кажется вернее...
← →
ANB (2008-04-23 13:40) [22]http://softwarer.ru/memory.html
Читать сомневающимся до полного просветления.
Пользуюсь этим способом практически везде, даже если нужен только один объект, т.к. заранее не знаешь, обойдешься одним или нет. И ни разу не ловил из-за этого АВ.
← →
Palladin © (2008-04-23 13:53) [23]Автор Александр Просторов, всемирно известный классик кодирования. всем пасть ниц
Тема многократного использования идентификатора объекта не раскрыта
← →
Arinyshka (2008-04-23 15:09) [24]Уффф... ну и дискуссия :)
А вот я еще один объект завожу... освобождаю по form.Close.
unit u;
interface
type
TSetPayFrm = class(TMGSprForm)
var
SetPayFrm : TSetPayFrm;
ListImage:TStringList;
implementation
procedure TSetPayFrm.InitImageList;
var MyStream: TStream; TempBitmap:TBitmap;
begin
try
ListImage:=TStringList.Create;
except
ListImage.Free;
end;
procedure TSetPayFrm.TbCloseClick(Sender: TObject);
begin
Close;
end;
procedure TSetPayFrm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
ListImage.Free;
Action := caFree;
end;
end.
Проблема в том, что он мне нужен и в других юнитах, на протяжении работы приложения. Поэтому в процедурке, создающей его, finaly меня не устраивает.
Но в случае except у меня 2 освобождения... Где я неправа?
← →
Рамиль © (2008-04-23 15:15) [25]Не надо загонять в try создание объекта. Если возникла ошибка при его создании, то вызывать деструктор лишено какого либо смысла.
← →
Palladin © (2008-04-23 15:18) [26]ListImage:=TStringList.Create; идет на верх над try
в finally пишем FreeAndNil(ListImage) ну или
ListImage.Free;
ListImage:=Nil;
в объявлении Var пишем
ListImage:TStringList=Nil;
← →
Восхищенный (2008-04-23 15:26) [27]Какая интересная дискуссия. И что интересно - ни одного повтора.
← →
Arinyshka (2008-04-23 15:48) [28]
> ListImage:=TStringList.Create; идет на верх над try
> в finally пишем FreeAndNil(ListImage) ну или
> ListImage.Free;
> ListImage:=Nil;
Подождите... разве я не потеряю значения nil? Я инициализировала и освободила?
← →
Arinyshka (2008-04-23 15:50) [29]ой, имела в виду список свой.
← →
Andy BitOff © (2008-04-23 16:09) [30]В Init в except FreeAndNil(ListImage), а ListImage:=TStringList.Create вынести над try. Далее по коду, если надо обратиться к ListImage делаешь проверку не Nil ли он.
← →
ANB (2008-04-23 16:31) [31]
> Palladin © (23.04.08 13:53) [23]
> Автор Александр Просторов, всемирно известный классик кодирования.
> всем пасть ниц
>
> Тема многократного использования идентификатора объекта
> не раскрыта
На SQL.ru сходи - познакомся.
← →
Anatoly Podgoretsky © (2008-04-23 16:32) [32]> Arinyshka (23.04.2008 15:09:24) [24]
> Проблема в том, что он мне нужен и в других юнитах, на протяжении работы приложения
В таком случае никаких переменных, переместить в класс, а доступ через контролируемое свойство Gettet/Setter и даже создавать извне не надо, Gettet/Setter с этим сами справятся. Никаких проблем с достоверность указателя не будет, всегда истинное.
← →
Loginov Dmitry © (2008-04-23 22:43) [33]http://matrix.kladovka.net.ru/index.php?page=tryfinally
← →
Игорь Шевченко © (2008-04-23 23:02) [34]ANB (23.04.08 13:40) [22]
> Читать сомневающимся до полного просветления.
Прочитал, не просветлился. Автор безусловно человек уважаемый, но к чему писать лишние строки, я так и не понял. Их и без того хватает, чтобы запутаться, мусорить нехорошо.
← →
Игорь Шевченко © (2008-04-23 23:04) [35]ANB (23.04.08 16:31) [31]
И эта...я понимаю, что локальные переменные обнулять после использования это конечно безусловно кошерно, но такты процессора являются тоже ресурсом и их следует расходовать экономно, что бы там раввин не говорил...
← →
ANB (2008-04-24 10:31) [36]Игорь Шевченко © (23.04.08 23:04) [35]
В случае с одним объектом, конечно, доп.строки являются лишними.
Это я по привычке пишу, чтобы потом не переделывать, если в процедуре понядобятся еще объекты.
Однако рассмотрим код :
Obj1 := nil;
Obj2 := nil;
Obj3 := nil;
Obj4 := nil;
Obj5 := nil;
try
Obj1 := TObj.Create;
Obj2 := TObj.Create;
Obj3 := TObj.Create;
Obj4 := TObj.Create;
Obj5 := TObj.Create;
...
работа с объектами и куча другого кода
finally
FreeAndNil(Obj1);
FreeAndNil(Obj2);
FreeAndNil(Obj3);
FreeAndNil(Obj4);
FreeAndNil(Obj5);
end;
Как без начального зануливания переменных под объекты это написать и корректно и читабельно ?
ЗЫ. Большуюя часть тактов процессора нынче съедают не наши приложения а рисование рюшечек операционки. Да и рюшечек наших приложений частенько тоже.
← →
Ega23 © (2008-04-24 10:35) [37]
> ANB (24.04.08 10:31) [36]
Зачем создание внутрь try тащить???
← →
ЮЮ © (2008-04-24 10:51) [38]> Зачем создание внутрь try тащить???
Затем, что ошибка может настичь и на Obj5 := TObj.Create; где же тогда освобождать Obj1 … Obj5
P/s/ Нафига только такими объектами пользоваться, которые ломаются уже в конструкторе. :)
В реальной жизни так печься только о TFileStream-e приходилось
← →
Ega23 © (2008-04-24 10:58) [39]
> Затем, что ошибка может настичь и на Obj5 := TObj.Create;
> где же тогда освобождать Obj1 … Obj5
А в таком случае надо по-хорошему так:Obj1 := TObj.Create;
try
Obj2 := TObj.Create;
try
Obj3 := TObj.Create;
try
.......
finally
Obj3.Free;
end;
finally
Obj2.Free;
end;
finally
Obj1.Free;
end;
← →
{RASkov} © (2008-04-24 10:59) [40]> [36] ANB (24.04.08 10:31)
> это написать и корректно и читабельно ?
Obj1 := TObj.Create;
try
Obj2 := TObj.Create;
try
Obj3 := TObj.Create;
try
Obj4 := TObj.Create;
try
Obj5 := TObj.Create;
try
...
работа с объектами и куча другого кода
finally
FreeAndNil(Obj5);
end;
finally
FreeAndNil(Obj4);
end;
finally
FreeAndNil(Obj3);
end;
finally
FreeAndNil(Obj2);
end;
finally
FreeAndNil(Obj1);
end;
или при уверенности, что в конструкторе не будет ошибок, то:
Obj1 := TObj.Create;
Obj2 := TObj.Create;
Obj3 := TObj.Create;
Obj4 := TObj.Create;
Obj5 := TObj.Create;
try
...
работа с объектами и куча другого кода
finally
FreeAndNil(Obj1);
FreeAndNil(Obj2);
FreeAndNil(Obj3);
FreeAndNil(Obj4);
FreeAndNil(Obj5);
end;
Но если честно, то у меня такого в коде никогда еще не встречалось :)
Страницы: 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 вся ветка
Форум: "Начинающим";
Текущий архив: 2008.06.08;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.055 c