Главная страница
    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;

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

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



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

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

Наверх





Память: 0.55 MB
Время: 0.003 c
2-1361469987
shup
2013-02-21 22:06
2013.12.08
матрица инциденции Delphi


15-1369665361
Rouse_
2013-05-27 18:36
2013.12.08
Пакет статей по перехвату.


3-1294832589
Андрей Пл
2011-01-12 14:43
2013.12.08
как программно запустит существующий пакет MS SQL


15-1371297794
_oxffff
2013-06-15 16:03
2013.12.08
Javapocalypse


15-1371673815
Юрий
2013-06-20 00:30
2013.12.08
С днем рождения ! 20 июня 2013 четверг





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