Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2013.12.08;
Скачать: [xml.tar.bz2];

Вниз

Чтобы локальные переменные в функциях   Найти похожие ветки 

 
Бездомный   (2011-10-06 13:35) [0]

обнулялись автоматически перед выполнением, есть такая директивка?

Если нет, можно ли как-нибудь написать такую процедурку LocalNullify:

function foo (param1, param2, ... paramN: AnyType1, ...): AnyType;
var
 ... тут неопределенное количество переменных, неопределенного размера ...
begin
 LocalNullify;
 //-- все локальные переменные обнулились, можно работать.
end;


Компилятор же некоторые типы (интерфейсы, динамические массивы) все-таки инициализирует.

P.S. Delphi 7, Delphi XE,XE2


 
Ega23 ©   (2011-10-06 13:40) [1]


>  есть такая директивка?


Нет.


> можно ли как-нибудь написать такую процедурку LocalNullify:


А нафига?


 
Бездомный   (2011-10-06 13:45) [2]


> Ega23 ©   (06.10.11 13:40) [1]

Чтобы не писать:

Errors := nil;
Output:= nil;
ProgressForm := nil;
Query:=nil;
try
 Errors := TStringList.Create;
 Output := TStringList.Create;
 ProgressForm := TProgressForm.Create;
 Query := TAdoQuery.Create;
finally
 Errors.Free;
 Output.Free;
 ProgressForm.Free;
 Query.Free;
end;


 
Dennis I. Komarov ©   (2011-10-06 13:54) [3]

Errors := TStringList.Create; try
 Output := TStringList.Create; try
   ProgressForm := TProgressForm.Create; try
     Query := TAdoQuery.Create; try
...
     finally
       Errors.Free;
     end;
   finally
     Output.Free;
   end;
 finally
   ProgressForm.Free;
 end;
finally
Query.Free;
end;


 
Dennis I. Komarov ©   (2011-10-06 13:55) [4]

только finally наоборот :-[


 
Бездомный   (2011-10-06 13:55) [5]


> Dennis I. Komarov ©   (06.10.11 13:54) [3]

Это еще больший ппц, на самом деле =(


 
Ega23 ©   (2011-10-06 14:04) [6]

Чтобы не писать:

Errors := nil;
Output:= nil;
ProgressForm := nil;
Query:=nil;

А их и не надо писать.


 
Бездомный   (2011-10-06 14:10) [7]


> Ega23 ©   (06.10.11 14:04) [6]




{Errors := nil;
Output:= nil;
ProgressForm := nil;
Query:=nil; -- убрали обнуление}
try
Errors := TStringList.Create;
Output := TStringList.Create;
ProgressForm := TProgressForm.Create; // <- тут исключение
Query := TAdoQuery.Create;
finally
Errors.Free;
Output.Free;
ProgressForm.Free;
Query.Free;  // <- Query остался неизвестно чем из стека.
end;



 
RWolf ©   (2011-10-06 14:10) [8]

Если в конструкторе присходит исключение, автоматически вызывается деструктор.
Зачем все эти try/finally?


 
Бездомный   (2011-10-06 14:10) [9]


{Errors := nil;
Output:= nil;
ProgressForm := nil;
Query:=nil; -- убрали обнуление}
try
 Errors := TStringList.Create;
 Output := TStringList.Create;
 ProgressForm := TProgressForm.Create; // <- тут исключение
 Query := TAdoQuery.Create;
finally
 Errors.Free;
 Output.Free;
 ProgressForm.Free;
 Query.Free;  // <- Query остался неизвестно чем из стека.
end;


 
Бездомный   (2011-10-06 14:11) [10]


> RWolf ©   (06.10.11 14:10) [8]

Речь идет о создании нескольких объектов сразу. Если исключение произойдет в TProgressForm.Create, то Errors и Output автоматически не освободятся.


 
RWolf ©   (2011-10-06 14:17) [11]

да, надо обнулять.


 
Ega23 ©   (2011-10-06 14:17) [12]


> Бездомный   (06.10.11 14:10) [9]

try
Errors := TStringList.Create;
Output := TStringList.Create;
ProgressForm := TProgressForm.Create; // <- тут исключение
Query := TAdoQuery.Create;
finally
Errors.Free;
Output.Free;
ProgressForm.Free;
Query.Free;  // <- Query остался неизвестно чем из стека.
end;


А нехер конструктор внутри try вызывать.

Errors := TStringList.Create;
Output := TStringList.Create;
ProgressForm := TProgressForm.Create; // <- тут исключение
Query := TAdoQuery.Create;
try
 .....
finally
// В обратном порядке
Query.Free;
ProgressForm.Free;
Output.Free;
Errors.Free;
end;

только это всё равно говнокод, в [3] Денис уже написал, как надо


 
Бездомный   (2011-10-06 14:20) [13]

В новых версиях можно както-то так сделать, все меньше писать:


with Objects(procedure
 Add(@Errors, TStringList.Create);
 Add(@Output, TStringList.Create);
 ...
end) do
try
 ...
finally
FreeAll;
end;


 
Бездомный   (2011-10-06 14:22) [14]


> только это всё равно говнокод, в [3] Денис уже написал,
> как надо

Да это понятно, но даже с 4 объектами уже будет громоздко.


 
Ega23 ©   (2011-10-06 14:26) [15]


> В новых версиях можно както-то так сделать


Можно. А нафига? С времени создания [0] прошёл почти час, у меня эти нестчастные

Errors := TStringList.Create;
try
 Output := TStringList.Create;
 try
   ProgressForm := TProgressForm.Create;
   try
     Query := TAdoQuery.Create;
     try
        // Do work here
     finally
       Query.Free;
     end;
   finally
     ProgressForm.Free;  
   end;  
 finally
   Output.Free;
 end;
finally
 Errors.Free;
end;


даже ребёнок бы набрал который текст одной рукой и одним пальцем набирает.


 
Ega23 ©   (2011-10-06 14:28) [16]


> Да это понятно, но даже с 4 объектами уже будет громоздко.

Есть мнение, что если приходится регулярно по 4 и более локальных объектов внутри функции-метода создавать то имеет смысл пересмотреть архитектуру.


 
Dennis I. Komarov ©   (2011-10-06 15:43) [17]


> Ega23 ©   (06.10.11 14:28) [16]
> Есть мнение

+1


 
Бездомный   (2011-10-06 16:08) [18]


> Ega23 ©   (06.10.11 14:28) [16]

Спасибо, ваше сообщение очень помогло разобраться в теме вопроса, не даром о вас слава ходит.


 
Ega23 ©   (2011-10-06 16:37) [19]


> Спасибо, ваше сообщение очень помогло разобраться в теме
> вопроса, не даром о вас слава ходит.


В данном случае сарказм не уместен.
Вы хотите "странного". Образно говоря, вы хотите заполучить асфальтовый каток, для того чтобы смело ездить по граблям, вместо того, чтобы просто по ним не ходить.
Никто не мешает и не запрещает:
1. создавать объекты внутри try.
2. не оборачивать каждый объект try..finally, а сделать его одним.
3. накатать простыню, как в [15].
4. создать стопицот локальных объектов в рамках одной процедуры.
По пунктам:
1. Создание объекта внутри try чревато Вашей проблемой.
2. Тут особых проблем не наблюдается, но нужна поддержка кода, т.к. уничтожать объекты нужно строго в обратном порядке, иначе чревато либо AV, либо мемликом, а в целом - и тем и другим одновременно.
3. Можно, но когда объектов дофига - довольно безобразная простыня получается.
4. Интереса ради, загляните в код VCL. Я вот наугад открыл Forms.pas, довольно большое количество локальных переменных увидел только в TCustomForm.WndProc (ну это и понятно).

Да, и у меня бывает по 6-8 локальных объектов. Особенно, когда какой-то тестик надо очень по-быстрому накатать. Но если это в "продакшн" идёт, то имеет смысл эти объекты с их логикой взаимодействия куда-то спрятать.


 
Бездомный   (2011-10-06 17:18) [20]

Вот это уже конструктивно, спасибо.

Если не затруднить объясните это:


> 2. Тут особых проблем не наблюдается, но нужна поддержка
> кода, т.к. уничтожать объекты нужно строго в обратном порядке,
>  иначе чревато либо AV, либо мемликом, а в целом - и тем
> и другим одновременно.


 
Бездомный   (2011-10-06 17:19) [21]

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


 
Ega23 ©   (2011-10-06 17:29) [22]

Так. Я малость напутал. Даже не малость.
Спутал с конструктором и деструктором и созданием-удалением локальных полей-объектов.


 
oxffff ©   (2011-10-06 17:30) [23]

Можно написать процедуру которая чистит от esp до ebp.
Но это не всегда будет безопасно, поскольку для анонимных методов например
создается временный объект, который можно таким образом затереть.

Самый простой способ запихать все в record и чистить ее как угодно.
также и финализатор к ней написать универсальный без необходимости каскадного finally ручками.


 
oxffff ©   (2011-10-06 17:33) [24]


> Самый простой способ запихать все в record и чистить ее
> как угодно.
> также и финализатор к ней написать универсальный без необходимости
> каскадного finally ручками.


Для record поставить align sizeof(pointer) и далее в цикле по полям с try except
и далее по списку если что надо дополнительно.


 
oxffff ©   (2011-10-06 17:34) [25]

У меня по рукой сейчас только SAP и ABAP. ;)
Delphi после работы.


 
Ega23 ©   (2011-10-06 17:41) [26]


> В этом варианте я вижу AV только в случае если какой-то
> из объектов поднимет исключение при освобождении.


Ну правильно, он у тебя ещё не создан, указатель на него может быть nil, а может и нет (что скорее всего), а ты ему Free пытаешься сделать.


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


> Речь идет о создании нескольких объектов сразу


Присоединяюсь к предыдущим ораторам - а нафиг ? если они все обязаны быть созданными для выполнения работы, стоит подумать об их композиции в класс.


 
Бездомный   (2011-10-06 18:22) [28]


> Ega23 ©   (06.10.11 17:41) [26]

Ничего страшного не будет, если выполнить
var Object: TObject;
begin
 Object := nil;
 Object.Free;
end;


> Присоединяюсь к предыдущим ораторам - а нафиг ?

Что-бы меньше писать.


> стоит подумать об их композиции в класс.

Согласен.


 
_Юрий   (2011-10-06 18:55) [29]

Можно запихать все в обжект-лист. Предварительно объявив хелпер к нему для удобства:

type
 TObjectListHelper = class helper for  TObjectList
 public
   function AddEx(Obj: TObject): Pointer;//добавить Obj и вернуть его же

List:=TObjectList.Create();
try
 localVar1:= List.AddEx(TClass1.Create);
 localVar2:= List.AddEx(TClass2.Create);
 localVar2:= List.AddEx(TClass3.Create);
...
finally
 List.Free;
end;

теперь, если исключение произошло в одном из конструкторов, этот экземпляр автоматически разрушится и не добавится в лист, ранее добавленные гарантированно разрушатся на файналли


 
_Юрий   (2011-10-06 18:56) [30]


>  localVar2:= List.AddEx(TClass3.Create);


localVar3:= List.AddEx(TClass3.Create);


 
Ega23 ©   (2011-10-06 19:31) [31]


> Что-бы меньше писать.


Ищи золотую середину.
Полное отсутствие декомпозиции - крайне неудобная и вредная вещь.
Бездумная декомпозиция всего и вся - тоже крайне неудобная и вредная вещь.


 
Dennis I. Komarov ©   (2011-10-06 20:29) [32]


> Ничего страшного не будет, если выполнить
> var Object: TObject;
> begin
>  Object := nil;
>  Object.Free;
> end;

А подумать?


 
Dennis I. Komarov ©   (2011-10-06 20:31) [33]

Вообще, какой смысл в "заниливание" ты вкладываешь?


 
Ega23 ©   (2011-10-06 20:31) [34]


> А подумать?


и если подумать, то ничего страшного не будет.


 
Ega23 ©   (2011-10-06 20:36) [35]


> Вообще, какой смысл в "заниливание" ты вкладываешь?


var
 fs: TFileStream;
begin
try
 fs := nil;
 try
   fs := TFileStream.Create("", fmCreate);
 finally
   fs.Free;
 end;
except
end;
end;


Правда вот нафига такой код нужен?


 
Дмитрий Белькевич   (2011-10-06 21:13) [36]


> Чтобы не писать:Errors := nil;Output:= nil;ProgressForm
> := nil;Query:=nil;


Вместо кучи локальных переменных делаем объект, который содержит Errors, Output, ProgressForm, Query. Создаем локально экземпляр этого объекта и в finally его разрушаем. Это если локальные переменные - инстансы классов.

Дальше. Если локальные - нединамические. Вместо кучи локальных переменных делаем запись, содержащую список этих переменных. Делаем записи ZeroMemory - при этом она вся очистится, не зависимо от того, сколько в ней реально переменных содержится.

Как-то так...


 
Дмитрий Белькевич   (2011-10-06 21:15) [37]

>Вместо кучи локальных переменных делаем объект

Читать: Вместо кучи локальных переменных делаем класс.


 
Dennis I. Komarov ©   (2011-10-06 21:46) [38]


> и если подумать, то ничего страшного не будет.

Утечка не страшно?

> Ega23 ©   (06.10.11 20:36) [35]

It"s for me?


 
Ega23 ©   (2011-10-06 21:54) [39]


> Утечка не страшно?


эээ... А где тут утечка????


> It"s for me?


Да не, это про смысл "заниливания".


 
Dennis I. Komarov ©   (2011-10-06 22:19) [40]


> эээ... А где тут утечка????


> begin
>  Object := nil;
>  Object.Free;
> end;

А деструктор для кого тут вызван будет?

З.Ы. Или пива уже много? :)


 
Ega23 ©   (2011-10-06 23:10) [41]


> А деструктор для кого тут вызван будет?


А он и не будет вызван. :)

procedure TObject.Free;
begin
 if Self <> nil then
   Destroy;
end;



> З.Ы. Или пива уже много? :)


Походу


 
Германн ©   (2011-10-07 01:08) [42]


> Dennis I. Komarov ©   (06.10.11 22:19) [40]


> Ega23 ©   (06.10.11 23:10) [41]

Вот не люблю и не использую FreeAndNil.
Так что на ваш диалог смотрю скептически. :(


 
Dennis I. Komarov ©   (2011-10-07 09:05) [43]

Ну и?
Ссылку потеряли, объект не уничтожили. Чем не утечка?


 
Dennis I. Komarov ©   (2011-10-07 09:31) [44]


> Вот не люблю и не использую FreeAndNil.

Эм, у нас тут немного другое: NilAndFree


 
Бездомный   (2011-10-07 10:07) [45]


> Ссылку потеряли, объект не уничтожили. Чем не утечка?


var Object: TObject;
begin
Object := nil;
Object.Free;
end;

Нет же никакой ссылки.


 
Ega23 ©   (2011-10-07 10:07) [46]


> Ссылку потеряли, объект не уничтожили.


Мы его и не создали, если чё.


 
Dennis I. Komarov ©   (2011-10-07 10:12) [47]


> Мы его и не создали, если чё.

Ну ты так больше не шути :)


 
Ega23 ©   (2011-10-07 10:15) [48]


var
 Object: TObject;
begin
 Object := nil;
 Object.Free;
end;


 
Dennis I. Komarov ©   (2011-10-07 10:24) [49]

тогда согласен, не страшно, тогда глупо...


 
Бездомный   (2011-10-12 17:53) [50]


> Dennis I. Komarov ©   (07.10.11 10:24) [49]

А это по твоему для потакания глупости сделано было?

procedure TObject.Free;
begin
if Self <> nil then
  Destroy;
end;


 
Dennis I. Komarov ©   (2011-10-12 18:14) [51]


> А это по твоему для потакания глупости сделано было?

Глупо пытаться сперва "занилить" ссылку, а после по ней пытаться уничтожить объект.


 
Dennis I. Komarov ©   (2011-10-12 19:11) [52]

Так же довольно глупо пытаться уничтожить заведомо не существующий объект.

> var Object: TObject;
> begin
> Object := nil;
> Object.Free;
> end;

А по сему, если предположить что код выложен не полностью и объект все-таки где-то когда-то создан
var Object: TObject;
begin
...
Object := nil;
Object.Free;
end;

, то получаем утечку памяти, что уже страшно...


 
Плохиш ©   (2011-10-13 01:58) [53]


> Бездомный   (06.10.11 13:45) [2]
>
> > Ega23 ©   (06.10.11 13:40) [1]
>
> Чтобы не писать:

Delphi вообще не правильная среда. Правильная среда должна иметь всего одну кнопку "Дай прогу".

PS. Прикольная такая ветка и до сих пор в основной.


 
Yaro2000   (2011-10-24 05:20) [54]

>> Dennis I. Komarov ©   (07.10.11 09:31) [44]
>> Вот не люблю и не использую FreeAndNil.
> Эм, у нас тут немного другое: NilAndFree

Пять баллов! :))))


 
RWolf ©   (2011-10-24 11:06) [55]

> Эм, у нас тут немного другое: NilAndFree

в оригинальной FreeAndNil так и делается, не?

procedure FreeAndNil(var Obj);
var
 Temp: TObject;
begin
 Temp := TObject(Obj);
 Pointer(Obj) := nil;
 Temp.Free;
end;


 
Плохиш ©   (2011-10-24 11:23) [56]


> RWolf ©   (24.10.11 11:06) [55]
> > Эм, у нас тут немного другое: NilAndFree
>
> в оригинальной FreeAndNil так и делается, не?
>
>

В каком месте он так делает? Может тебе поизучать скопированный тобой же код несколько раз до полного просветления.


 
RWolf ©   (2011-10-24 11:30) [57]


> [56]

ссылку обнулили, объект освободили.
с точки зрения вызывающего — вполне себе NilAndFree.



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

Форум: "Основная";
Текущий архив: 2013.12.08;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.6 MB
Время: 0.003 c
8-1233672337
salamander
2009-02-03 17:45
2013.12.08
Как сделать повтор звука в компоненте MediaPlayer?


2-1361469987
shup
2013-02-21 22:06
2013.12.08
матрица инциденции Delphi


15-1371318845
Пит
2013-06-15 21:54
2013.12.08
Управление пользователями Firebird


15-1371668899
Jeer
2013-06-19 23:08
2013.12.08
Памяти наших Учителей посвящается..


15-1371273493
zxzx
2013-06-15 09:18
2013.12.08
Помогите настроить сетевые карты





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский