Форум: "Основная";
Текущий архив: 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