Форум: "Прочее";
Текущий архив: 2014.11.30;
Скачать: [xml.tar.bz2];
ВнизТрюки в Delphi Найти похожие ветки
← →
Виктор1985 (2014-04-22 13:11) [0]Приветствую! Наткнулся сегодня на статью
http://wiert.me/2014/04/21/today-i-learned-i-didnt-know-about-this-syntax-for-properties-via-roman-yankovsky-google/
Собственно захотелось узнать, может у кого в загашнике есть своя порция интересных трюков?
От себя:
Получение смещения поля в структуре
//Получение смещения поля TypeInfo в структуре типа PackageInfoTable
LongWord(@PackageInfoTable(nil^).TypeInfo))
← →
Игорь Шевченко © (2014-04-22 13:25) [1]There is no limit to how bad things can get :)
← →
Kerk © (2014-04-22 13:37) [2]Вот тут еще подборка редко используемых возможностей
http://delphi.org/2014/02/hidden-features-in-the-delphi-object-pascal-language/
← →
Виктор1985 (2014-04-22 14:03) [3]Вот еще вспомнил, понадобилось обратиться к байтам LongWord"a, как то затупил и начал сдвиги применять, маски... не сразу вспомнил про приведение типов, а когда вспомнил переписал и вышло очень читабельно:
type
B32 = array[1..4] of Byte;
..
var
T0: LongWord;
B32(T0)[1] //читаем первый байт
B32(T0)[2] //читаем второй байт
← →
Дмитрий СС (2014-04-22 14:55) [4]Вот бы придумали способ обнулять локальные переменные автоматически. Хотя бы объектовые только.
← →
junglecat (2014-04-22 15:20) [5]> обнулять локальные переменные автоматически
а нафига?
← →
Dimka Maslov © (2014-04-22 15:56) [6]
> Kerk © (22.04.14 13:37) [2]
Такое ощущение, что список составляли ламеры-батонокидатели, которые внезапно что-то где умудрились прочитать...
← →
sniknik © (2014-04-22 16:01) [7]> обнулять локальные переменные автоматически. Хотя бы объектовые только.
интерфейсы. пользуйтесь интерфейсами.
← →
Ega23 © (2014-04-22 16:04) [8]
> Вот бы придумали способ обнулять локальные переменные автоматически.
Не обнулять, а приводить к начальному состоянию. Что далеко не всегда 0 или nil
← →
junglecat (2014-04-22 16:09) [9]> приводить к начальному состоянию
автоматически, путем считывания мыслей программера
← →
Виктор1985 (2014-04-22 16:13) [10]> приводить к начальному состоянию
возможность задавать как для глобальных переменных, типа
var
Node: TNode = nil;
begin
//...
приводило бы к тому что бы код превращался в
var
Node: TNode;
begin
Node := nil;
//...
← →
Виктор1985 (2014-04-22 16:20) [11]Вот еще, недавно наткнулся. Возможность включать изменения констант. По сути такая константа является глобальной переменной доступной только в области видимости используемой функции. Вот пример:
procedure MaxOrNormalForm(AForm: TForm; AMax: Boolean);
const
{$J+}
LastBounds: TRect = ();
{$J-}
begin
if AMax then
begin
LastBounds := AForm.BoundsRect;
AForm.FormStyle := fsStayOnTop;
AForm.BorderStyle := bsNone;
AForm.BoundsRect := Screen.MonitorFromWindow(AForm.Handle).BoundsRect;
end
else
begin
AForm.FormStyle := fsNormal;
AForm.BorderStyle := bsSizeable;
AForm.BoundsRect := LastBounds;
end;
end;
← →
Ega23 © (2014-04-22 16:29) [12]
> Возможность включать изменения констант.
Гхм... Это ещё в турбопаскале пятом было. Называлось "типизированная константа".
← →
Германн © (2014-04-22 16:49) [13]
> Ega23 © (22.04.14 16:29) [12]
>
>
> > Возможность включать изменения констант.
>
>
> Гхм... Это ещё в турбопаскале пятом было. Называлось "типизированная
> константа".
>
На самом деле это возможность вЫключать изменения констант. Чего в ТР5 не было :)
← →
Дмитрий СС (2014-04-23 00:59) [14]
> а нафига?
К примеру, в методе используется два стринглиста и один стрим. По идее три вложенных try finally, но можно и так:
Sl1:=nil;
Sl2:=nil;
MS:=nil;
Try
Sl1:=Tstringlist.create;
Sl2:=Tstringlist.create;
MS:=Tmemorystream.create;
...
Finally
Sl1.free;
Sl2.free;
Ms.free;
End;
Плюсов у этого подхода полно, но утоляет обниливание писать. Хотя есть идея:
Var
LM:IMyLocalManager;
LM:=TMyLocalManager.Create([@Sl1, @Sl2, @MS]);
Дальше создаём, удаляем или не удаляем. Если что LM при освобождении сам все удалит))
← →
Ega23 © (2014-04-23 07:44) [15]
> Плюсов у этого подхода полно
В данном примере нет ни одного плюса. А вот минусов - таки полно.
← →
junglecat (2014-04-23 08:38) [16]> Плюсов у этого подхода полно
не видно ни одного.
почему create должно быть внутри try?
← →
KilkennyCat © (2014-04-23 09:04) [17]некоторые трюки могут дорого обойтись после компиляции. надеюсь, там после каждого трюка написано что-нить типа: сокращает ресурсы на 5% ускоряет на 10% и дает +5% к уверенности?
← →
junglecat (2014-04-23 09:29) [18]> и дает +5% к уверенности?
и +20 к карме
← →
brother © (2014-04-23 09:42) [19]+5 к магии - 30 к понятности и стабильности кода...
← →
Palladin © (2014-04-23 10:28) [20]
> Дмитрий СС (23.04.14 00:59) [14]
очень глупое решение
Finally
Sl1.free; // бац эксцепш
Sl2.free; // лик
Ms.free; // лик
End;
а че там про плюсы то? а то, кроме упоминания, что они есть больше ничего и нет
← →
имя (2014-04-23 10:32) [21]Удалено модератором
← →
Rouse_ © (2014-04-23 19:41) [22]
> Плюсов у этого подхода полно
Огласите весь список, пожалуйста… ©
← →
Дмитрий СС (2014-04-24 04:21) [23]
> очень глупое решение
Если у вас ексепшн на освобождении простого стандартного класса, то скорее всего уже чтото сильно пошло не так.
Плюс, самый главный в том, что не нужно городить большое количество Try finally.
+ Проще выбирать момент создания и смерти объекта (freeandnil).
Впрочем, бесполезно что-либо объяснять. В соседней ветке решили сложную алгоритмическую задачу, а тут понять не могут, почему создание объекта внутри try.
← →
Ega23 © (2014-04-24 07:51) [24]
> что не нужно городить большое количество Try finally.
Зато придётся писать большое количество FreeAndNil, либо обниливать все локальные переменные в самом начале.
Надеюсь, не надо объяснять, почему?
← →
jack128_ (2014-04-24 10:18) [25]
> > что не нужно городить большое количество Try finally.
>
>
> Зато придётся писать большое количество FreeAndNil, либо
> обниливать все локальные переменные в самом начале.
> Надеюсь, не надо объяснять, почему?
если использовать вложенные try finally, то для создания/уничтожения N объектов нам понадобится 5*N строк кода. Для метода Дмитрий СС понадобится 3 + 3*N строк кода. То есть уже для двух объектов уже короче как Дима писать.
> очень глупое решение
>
> Finally
> Sl1.free; // бац эксцепш
> Sl2.free; // лик
> Ms.free; // лик
> End;
Ты так говоришь, как будто если б ты написал вложенные try finally, то мем лика бы не было :-D
← →
Игорь Шевченко © (2014-04-24 10:28) [26]jack128_ (24.04.14 10:18) [25]
Писать надо не коротко, а понятно.
← →
Ega23 © (2014-04-24 10:39) [27]
> если использовать вложенные try finally, то для создания/уничтожения
> N объектов нам понадобится 5*N строк кода. Для метода Дмитрий
> СС понадобится 3 + 3*N строк кода. То есть уже для двух
> объектов уже короче как Дима писать.
code template сам все finally вставит, с end-ом и отступами.
А так всё ручкаме придётся писать.
← →
Rouse_ © (2014-04-24 10:52) [28]
> Плюс, самый главный в том, что не нужно городить большое
> количество Try finally.
А в чем плюс?
> Проще выбирать момент создания и смерти объекта (freeandnil).
А зачем? Темболее есть другие более безопасные методы для этого, даже try..finally писать не нужно будет.
> jack128_ (24.04.14 10:18) [25]
т.е. ты считаешь это правильный подход? :)
Подумай прежде чем ответить, я пока за топорм схожу ;)
← →
jack128_ (2014-04-24 11:22) [29]А код [14] не понятен?
← →
Ega23 © (2014-04-24 11:34) [30]
> А код [14] не понятен?
Я тебе приватно сказал, теперь публично повторюсь: я на этот код втыкал где-то с минуту, при этом совершенно не обратил внимание на то, что локальные переменные перед try принудительно обниливаются.
ИМХО, это как Destroy вместо Free использовать. В тех самых 95% случаев, когда мы юзаем локальный класс, то особой разницы нет. При разрушении вложенных объектов - тоже нет, если в конструкторе исключение не поднимается.
← →
junglecat (2014-04-24 11:35) [31]такая интригующая тема намечалась, а свалились в банальный try...)
← →
Ega23 © (2014-04-24 11:46) [32]Удалено модератором
← →
Rouse_ © (2014-04-24 11:55) [33]Удалено модератором
← →
jack128_ (2014-04-24 11:59) [34]
> такая интригующая тема намечалась,
ну вот интересная вещь об overload, о которой не все знают.
По крайней мере в последних версия эта директива работает не только внутри одного модуля.unit unti1;
inteface
procedure DoWork(i: Integer); overload; // в старых дельфях был варнинг, что overload не нужен
...unit unti2;
inteface
procedure DoWork(str: string); overload;
...unit unti3;
uses
Unit1, Unit2;
...
DoWork(10); // компилируется. А вот если убрать overload хотя с одной функции DoWork - то не компилируется.
← →
Владислав © (2014-04-24 18:15) [35]Ega23 © (23.04.14 07:44) [15]
"В данном примере нет ни одного плюса. А вот минусов - таки полно."
Огласите весь список, пожалуйста. :)
Сам я обычно так не пишу, но интересно, что же такого плохого в конструкции?
← →
Rouse_ © (2014-04-24 18:30) [36]
> Владислав © (24.04.14 18:15) [35]
1. Это семантически неверная реализация кода, что приводит к затруднению читаемости.
2. Это идеологически неверно выстроенный подход, допускающий наличие утечек памяти в объектов, напрямую не связанными с ошибками.
3. Это делается гораздо проще, на основе смартпойнтеров, не требующих try..finally блоков
4. это затрудняет поиск возникновения ошибки, посредством инструментов наподобие FastMM (в логе которого будет куча неосвобожденных обьектов всвязи с пунктом 2)
5. Человек, настолько уверенный в своей правоте при применении данного подхода давным давно должен вообще отказаться от использовании try..finally, ибо зачем? Если мы являемся профессионалом, то пишем код, такого-же качества, стало быть излишества в виде SEH фреймов для нас лишние, впрочем как и вызовы Free (зачем перестраховываться, ведь мы профессионалы - нужно работать напрямую с Dectroy? :)
6. До кучи, раз уж мы боремся за количество строчек кода в виде 5*N строк кода против 3 + 3*N - нужно как минимум вспомнить что писать можно несколько инструкций в одну строчку. Такой код программы будет очарователен и самое главное будет занимать очень мало строчек, что несомненно является громадным преимуществом :)
← →
junglecat (2014-04-24 18:31) [37]> будет занимать очень мало строчек, что несомненно является
> громадным преимуществом
индусы с тобой не согласятся: у них построчная оплата труда
← →
Rouse_ © (2014-04-24 18:32) [38]
> junglecat (24.04.14 18:31) [37]
> индусы с тобой не согласятся: у них построчная оплата труда
Ассемблерщики у индусов - олигархи как минимум :)))
← →
junglecat (2014-04-24 18:34) [39]> Ассемблерщики у индусов
это нонсенс. Они предпочитают VB
← →
Rouse_ © (2014-04-24 18:36) [40]
> junglecat (24.04.14 18:34) [39]
Между прочим язык - огонь, только OnErrorGoToNext чего стоит, все try нервно курят в сторонке :)
← →
Ega23 © (2014-04-24 18:55) [41]
> 5*N строк кода против 3 + 3*N
Кстати, о пцыцах. А много ли у вас такого кода, когда в одной процедуре-методе создаётся более трёх локальных объектов?
← →
vuk © (2014-04-24 19:02) [42]to Rouse_ © (24.04.14 18:30) [36]:
> Человек, настолько уверенный в своей правоте при применении
> данного подхода давным давно должен вообще отказаться от
> использовании try..finally, ибо зачем?
Сопцтвенно, например, FastReport наполовину так и написан. Типичное оттуда:TempStream := TMemoryStream.Create;
TempStream.CopyFrom(Stream, n - Stream.Position);
TempStream.Position := 0;
p.Picture.Graphic.LoadFromStream(TempStream);
TempStream.Free;
Ну и несколько free в одном finally - тож в ассортименте.
← →
junglecat (2014-04-24 19:06) [43]> Сопцтвенно, например, FastReport наполовину так и написан
видимо, Fast - не оттого, что быстро работает, а быстро написан
← →
Kerk © (2014-04-24 19:11) [44]try/finally - это неожиданно больной вопрос. Я даже не ожидал :)
У меня в SourceOddity есть проверка на то, чтоб объект создавался вне try/finally блока. Но реально многие просят сделать исключение для случаев, когда перед этим есть присваивание nil. Вот все думаю, проявить принципиальность или пойти на поводу :)
← →
Rouse_ © (2014-04-24 19:19) [45]
> Вот все думаю, проявить принципиальность или пойти на поводу :)
Не порть хороший продукт - откажу в тестировании :))))
← →
Rouse_ © (2014-04-24 19:20) [46]
> откажу в тестировании :))))
Щас это называется модным словом - введу санкции :)))))))))
← →
Владислав © (2014-04-24 19:35) [47]Rouse_ © (24.04.14 18:30) [36]
Надцать лет назад у нас возник спор по этому же поводу с jack128, если мне склероз не изменяет. С тех пор, видимо, ничего не изменилось. Раньше я тоже Вашего мнения придерживался.
По пунктам выскажу свое мнение. Обратите внимание, не ради спора, а ради расширения кругозора.
1. Читаемость затруднена только тому, кто не знает такую конструкцию. Некоторые начинающие вообще не знают про конструкцию try finally, но это не повод ее не применять.
2. То есть код вида:// Получаем ресурс.
try
// Работаем с ресурсом.
finally
// Освобождаем ресурс, но при этом происходит исключение.
end;
вполне допустим для утечек памяти, а обсуждаемый код для утечек не допустим? Причину допустимости утечек памяти в некоторых случаях назовите, пожалуйста?
3. Вопрос был не про умные указатели. Не в тему пункт.
4. Тут немного неясно. Насколько часто в деструкторе возникают утечки памяти, которые постоянно нужно разыскивать. Может пересмотреть подход к исключениям в деструкторе?
5. Вообще мимо. Настолько не в тему, насколько предложение отказаться от классов.
6. А тут совсем "молоко". Количество строчек кода было плюсом, а не минусом.
← →
Rouse_ © (2014-04-24 20:03) [48]
> Причину допустимости утечек памяти в некоторых случаях назовите,
> пожалуйста?
Так вопрос не стоял - утечки памяти не допустимы априори, а вот допускать новые, из-за неверно написанного кода, есть глупость.
Это кстати ответ на пункт 4.
← →
Ega23 © (2014-04-24 20:41) [49]
> Вот все думаю, проявить принципиальность или пойти на поводу :)
Сделай чекбокс. Галочка включена - иди. Выключена - не иди.
Состояние галочек, разумеется, сохраняй в ini-файл.
← →
Виктор1985 (2014-04-24 21:01) [50]> Rouse_ © (24.04.14 18:30) [36]
Зачем вообще может понадобится проектировать деструктор так что бы там исключения поднимать? Объект когда умирает нужно давать ему спокойно умереть, он же больше не нужен.
В С++ если мне не изменяет память вообще от исключения в деструкторе рантайм падает, и живут неплохо, с утечками справляются.
Ну а по поводу стандартных исключений типа OutofMemory, которые могут возникнуть в деструкторе, если уж такое случилось то все равно как приложение умрет.
← →
Rouse_ © (2014-04-24 21:09) [51]
> Виктор1985 (24.04.14 21:01) [50]
> Зачем вообще может понадобится проектировать деструктор
> так что бы там исключения поднимать?
А кто сказал что кто-то его так проектирует? 0_о
← →
Владислав © (2014-04-24 21:28) [52]"А кто сказал что кто-то его так проектирует? 0_о"
А если его никто так не проектирует, а исключение в деструкторе есть, какой смысл заботиться об утечках памяти? Приложение падает, а мы стараемся, чтобы память не утекала? Пусть лучше громко упадет, чем долго будет неправильно работать. Нет?
Ну а тогда получается, что обсуждаемый вопрос и в том и другом виде имеет право на существование.
← →
Rouse_ © (2014-04-24 21:40) [53]
> какой смысл заботиться об утечках памяти?
Пункт 4.
Объясняю на пальцах, есть приложение и 3 объекта реализованных вот таким кривым способом, как показано выше + подключенный FastMM.
Приложение уходит бетатестеру.
Происходит падение в деструкторе первого класса FastMM показывает утечку по всем трем. Дальше объяснять?
← →
Владислав © (2014-04-24 21:51) [54]Не стоит дальше. Дальше понятно. Дальше смотрим в лог исключений и ремонтируем косяки в своей программе. После ремонта косяков пункт 4 становится неактуальный.
← →
Rouse__ (2014-04-24 21:54) [55]Это только первый этап, а теперь у нас приложение целиком криво написанное, на выходе мегабайты логов из-за падений, как будем вычислять проблемное место? А ведь все просто, будучи правильно написанным, лог выведет только проблемные классы, не более того
← →
Владислав © (2014-04-24 21:57) [56]"А ведь все просто, будучи правильно написанным, лог выведет только проблемные классы, не более того"
Саш, а правильно написанное часто в деструкторе падает? ;)
← →
Rouse__ (2014-04-24 22:02) [57]50/50 либо падает либо нет :)
← →
Владислав © (2014-04-24 22:09) [58]Саш, да ну нафиг. Есть у Вас пример из реальной программы?
← →
Rouse__ (2014-04-24 22:16) [59]Половина багтрекера забито :))) Причины такие бывают что я даже с пьяных глаз предположить не мог :)
← →
Rouse__ (2014-04-24 22:19) [60]Вон сегодня с женькой решали, код простой topendialog создали отобразили, передали результат функции разрушаем - оппа, у 148 человек за три месяца на деструкторе диалога AV, сиди и думай - откуда?
← →
Rouse__ (2014-04-24 22:20) [61]Причем пользователей у нас за 200 тыщ а возникло только у 148-и за такой длительный период
← →
Rouse__ (2014-04-24 22:22) [62]Точнее не у 148 пользовотелей, а всего 148 раз :))
← →
Владислав © (2014-04-24 22:23) [63]Не верю. Я, конечно, не скажу, что я в этом вопросе принципиален и категоричен, понимаю, что "всякий овощ...", но 50/50 исключения в деструкторе? Не верю. :)
← →
Владислав © (2014-04-24 22:25) [64]"Вон сегодня с женькой решали, код простой topendialog"
Занимательно. Нашли причину? Поделитесь информацией.
← →
Rouse__ (2014-04-24 22:27) [65]Во, еще одну чудную ошибку вспомнил, есть у меня формочка, показывающая превью документа, закрывается она с анимацией причем шибко быстро, но если в этот момент пользователь успеет кликнуть на стороннем окне и формочка потеряет фокус, то есть шанс что произойдет падение в деструкторе, и если смотреть по стеку то в районе процедуры IsFormSizeStored как-то так кажется
← →
Rouse__ (2014-04-24 22:28) [66]Еще не решили ибо не знаем даже с какой стороны подойти и как возпроизвести
← →
Rouse__ (2014-04-24 22:29) [67]50/50 - это шутка из анекдота про блондинку и динозавра :)
← →
Ega23 © (2014-04-24 22:34) [68]Удалено модератором
← →
Владислав © (2014-04-24 23:04) [69]"50/50 - это шутка из анекдота про блондинку и динозавра :)"
Ясно. Получается, на несколько обсуждаемых случаев (пока два, может еще вспомните), пожалуй, несколько миллионов finally? Говорит ли это о том, что конструкция не имеет права на существование? ;)
"Я - д"Артаньян!"
Это вообще самый серьезный трюк. Это почти что кнопка "Сделать все хорошо". :)
← →
Rouse__ (2014-04-24 23:08) [70]На самом деле их сотни на моей памяти те которые помню, но слишком долго описывать, почти у каждого есть конкретная причина, обычно внешняя со стороны ос, сети или файловой системы
← →
Rouse__ (2014-04-24 23:09) [71]Но если смотреть по багтрекеру их конечно на порядок больше, всеж не упомнить
← →
Rouse__ (2014-04-24 23:16) [72]Вот еще интересная ошибка, но уже не с деструктором связанная. Мы сохраняем данные чере ixmldocument на ворме edit вводим в него произвольный текст а потом нажимаем ctrl+Shift+6 и получившийся текст пишем в атрибуты узла после чего сохраняем xml. Собственно все - теперь этот документ не откроется из-за ошибки загрузки.
Msxml не будет экранировать этот символ, что есть глюк.
← →
Владислав © (2014-04-24 23:44) [73]Ну в итоге все равно "всякий овощ...". Понятно, что думать нужно...
Спасибо за дискуссию! :)
← →
Ega23 © (2014-04-24 23:50) [74]Удалено модератором
← →
Владислав © (2014-04-24 23:55) [75]Удалено модератором
← →
Rouse__ (2014-04-25 00:03) [76]Удалено модератором
← →
Германн © (2014-04-25 03:09) [77]Удалено модератором
← →
Ega23 © (2014-04-25 10:28) [78]Удалено модератором
← →
junglecat (2014-04-25 10:42) [79]Удалено модератором
← →
Ega23 © (2014-04-25 11:02) [80]Удалено модератором
← →
kilkennycat © (2014-04-25 12:30) [81]самые мерзкие ошибки - аппаратные. особенно, когда знаний ноль. когда-то давно моя прога в момент демонстрации покупателям не заработала, ибо демонстрировалась на машине с интел-процессором, а собиралась на амд.
причину искал недели две.
никаких хитрых трюков, никаких асмов, ничего...
решилось компиляцией под интелом. после этого работало на обоих.
← →
junglecat (2014-04-25 13:36) [82]> самые мерзкие ошибки - аппаратные
вот например билетный принтер, будучи подключенным через обычный ком-порт, работает отлично, а через его usb-эмулятор начинает глючить, а то и вовсе отказывается печатать. Особенно под виндой выше ХР
← →
icWasya © (2014-04-25 14:33) [83]> самые мерзкие ошибки - аппаратные
Было ещё во времена Dos и TurboPascal.
У одного клиента оказалась машина без сопроцессора, а в конфиге биос было указано, что таковой есть.
← →
Германн © (2014-04-26 03:01) [84]
> junglecat (25.04.14 13:36) [82]
>
> > самые мерзкие ошибки - аппаратные
>
> вот например билетный принтер, будучи подключенным через
> обычный ком-порт, работает отлично, а через его usb-эмулятор
> начинает глючить, а то и вовсе отказывается печатать. Особенно
> под виндой выше ХР
Это не аппаратные ошибки.
← →
Kerk © (2014-04-26 20:29) [85]Вот тут еще с мест сообщают, что есть еще такой синтаксис:
type
TM128 = Record
V: Byte;
end align 16; // SizeOf(TM128) = 16 bytes !!
https://plus.google.com/111201640882651724054/posts/C9Pu1qZdWxt
Страницы: 1 2 3 вся ветка
Форум: "Прочее";
Текущий архив: 2014.11.30;
Скачать: [xml.tar.bz2];
Память: 0.67 MB
Время: 0.003 c