- 1
Знаете ли Вы, что в FreePascal блоки try..finally/except не работают в контексте DLL?
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
−18
Знаете ли Вы, что в FreePascal блоки try..finally/except не работают в контексте DLL?
Dr_Stertor 10.01.2017 17:27 # 0
bormand 10.01.2017 18:32 # +1
Не ловят исключения или вообще не компилятся?
rotretS 10.01.2017 19:44 # +1
bormand 10.01.2017 19:46 # 0
З.Ы. Ну и исключение брошено из той же самой дллки, или из функции какой-то другой дллки или самого экзешника?
rotretS 10.01.2017 20:39 # 0
bormand 10.01.2017 20:41 # 0
Лол, т.е. dll'ка даже свои собственные исключения не видит в упор?
З.Ы. Попробуй на динамический рантайм переключиться, если оно умеет (и в экзешнике и в дллке само собой).
rotretS 10.01.2017 21:14 # 0
bormand 10.01.2017 21:16 # 0
rotretS 10.01.2017 21:17 # 0
Приложение так или иначе всё равно грузит *.bpl-пакет в память, значит, дело не в выйгрыше в размере занимаемой памяти. А в чем тогда?
bormand 10.01.2017 21:19 # +1
В общем менеджере памяти и общей инфе о классах. Все дллки и экзешка с общим рантаймом как-бы сливаются в одно целое. Можно спокойно юзать ООП и прочие ништяки на всю катушку.
rotretS 10.01.2017 21:20 # 0
Wow. Но это же замечательно. Можно запилить свое ООП с блэк-джэком и шлюхами.
bormand 10.01.2017 21:20 # +1
В общем-то да.
bormand 10.01.2017 21:29 # +2
rotretS 10.01.2017 21:32 # +1
Хз, ошибка это или нет. Система ведь всё равно подчистит. Но в своих прогах я очень щепетильно отношусь к утечкам.
bormand 10.01.2017 21:35 # 0
Ну это же не утечка, просто объект, закешированный в глобалку. Многие либы этим страдают.
barop 10.01.2017 21:36 # 0
bormand 10.01.2017 21:36 # 0
З.Ы. "Любой static" всё-таки не лежит в куче.
barop 10.01.2017 21:53 # +1
Плохо когда они плодятся, когда через N часов работы у тебя куча такая что на тебя ООМКиллер поглядывает
rotretS 11.01.2017 17:56 # 0
Здесь другой случай. Деструктор не вызывается вовсе и память освобождает сама система, в момент закрытия приложения.
bormand 10.01.2017 21:42 # +1
rotretS 10.01.2017 21:44 # 0
Т.е. обеспечивается "резиновый" размер памяти, но это даётся ценой размещения в ней висячих объектов?
guest 10.01.2017 21:48 # −2
rotretS 10.01.2017 21:48 # +1
Речь о том, что сборщик мусора должен быть активен вплоть до завершения работы проги, а сам при этом утечет.
barop 10.01.2017 22:05 # 0
Не поможешь?
rotretS 10.01.2017 22:21 # 0
Я так понимаю, что идёт обмен шила на мыло.
Что представляет собой GC? Наверняка, это какой-то глобальный объект для подчищаемой проги, который управляет ее памятью. Если его инстанс создаётся каждый раз для каждой проги, по завершению ее работы он "утекает" - т.е., он же не может деаллоцировать сам себя - его прихлопывает система.
bormand 10.01.2017 22:22 # 0
Да и хуй с ним, он ничтожно мал по сравнению с тем, что он успевает почистить за свою жизнь.
З.Ы. Утечки мало кого беспокоят после смерти. Главное - чтобы они не мешали при жизни :)
barop 10.01.2017 22:24 # 0
Почему шило на мыло то? Ну да, виртуальная машина занимает память. При выключении машины эта память освобождаеца.
Что плохого?
rotretS 10.01.2017 22:26 # 0
Дополнительный поток, который чистит память своего же процесса?
barop 10.01.2017 22:44 # 0
Ну точнее это конечно зависит от реализации. Думаю что ты имеешь право реализовать так, как тебе удобно, но вот JVM это так, думаю то и в .NET так же.
barop 10.01.2017 21:51 # 0
Где, по твоему, лежит синглтон со своими полями?
CHayT 10.01.2017 21:53 # +1
Это норма, и такое вообще часто используется. Для быстродействия в том числе: если программа работает недолго и вызывается часто (что-то типа grep или cat) то нефиг ей перед завершением в куче рыться, деаллоцируя заведомо обречённые на гибель объекты.
barop 10.01.2017 21:55 # 0
bormand 10.01.2017 21:56 # 0
barop 10.01.2017 22:03 # +1
bormand 10.01.2017 22:05 # 0
Т.е. GC - говно, т.к. освобождает её в самый-самый последний момент, когда аллокатор вот-вот обломится?
barop 10.01.2017 22:10 # 0
ладно, я понял разницу: файл может быть нужен конкретный, а память не важно какая: главное, чтобы была
CHayT 10.01.2017 22:13 # +3
Тормозной, неполноценный, ненадёжный, ненужный.
То ли дело машина Тьюринга с бесконечной лентой.
bormand 10.01.2017 22:17 # 0
Лента - медленная хуйня с последовательным доступом. То ли дело бесконечная память...
З.Ы. Но как эту бесконечную память адресовать?
barop 10.01.2017 22:19 # 0
С помощью регистра бесконечного размера конечно же
CHayT 10.01.2017 22:23 # +2
barop 10.01.2017 22:17 # +2
Разница в использовании по сравнению с GC только в невозможности выпилить isle of isolation, и потому нужно было понимать в какую сторону можно делать strong ref, а в какую -- нет, что порождало говнопаттерны типа "strong weak dance", зато никто не широёбился в фоне и не искал пути к объекту из стеков потока и пермгена. Может быть потому айфон дольше держит зарядку, чем андроидные девайсы?;)
Но если совсем по честному, то я от ручного управления памятью не умирал: надо было быть очень внимательным
CHayT 10.01.2017 22:22 # 0
Не знаю, как в ObjC, но в йеху он меня не впечатлил.
http://govnokod.ru/19104
barop 10.01.2017 22:33 # 0
Если у тебя A ссылается на B, а B на A то одна из ссылок должна быть weak (тоесть на каунтинг не влиять и обнуляца).
В твоем примере тоже самое только A и B у тебя инстансы одного класс.
Кстати, в UIKit есть очень четкие конвенции на этот счет: контроллер имеет ссылки на свои элементы, а они на него weak, и потому когда на контроллер никто не ссылается то его можно уебать, и его потомки дадут дуба вместе с ним. А буть ссылки жесткие -- ты бы их никогда бы не удалил
CHayT 10.01.2017 22:36 # 0
barop 10.01.2017 22:40 # 0
Вот тут p ссылается на p0: var p = R(a : p0)
А вот тут p0 на p: p0._a = p
Обе ссылки стронговые. Objc мог смело сделать memory leak, а сырой стриж запутался и наступил себе на шнурки.
В любом случае ты НЕ прав: ты сделал некрасиво.
CHayT 10.01.2017 22:44 # 0
> if leak
> test(noLeak, leak: false)
barop 10.01.2017 22:50 # 0
Я тебя верно понял? У меня нет ябла просто чтобы собрать, а из твоих комментов я сделал именно такой вывод.
CHayT 10.01.2017 22:57 # 0
barop 10.01.2017 23:01 # 0
В общем я согласен с тем, что свифт повел себя как говно. Но это вопрос не к RC а его реализации.
Было бы здорово, если бы reference cycle был бы объявлен UB
barop 10.01.2017 23:05 # 0
bormand 10.01.2017 23:06 # 0
Развалится же сразу.
barop 10.01.2017 23:09 # 0
Все кошерненько соберется и уйдет в помойку.
В Objc посылка сообщения нилу валидна, думаю что и в свифте тоже.
CHayT 10.01.2017 23:11 # 0
Будет точно то же самое, что и в случае с leak:false.
bormand 10.01.2017 23:12 # 0
Угу, даже не успев построиться (что я и имел в виду под развалится). Как я тебе вилкой на виках буду список строить?
З.Ы. Или ты только про последний замыкающий элемент?
bormand 10.01.2017 22:57 # 0
Ну тут, в общем случае, задача хреновая. Можно разве что заменить рекурсию очередью. А чтобы не выделять память при освобождении памяти - строить эту очередь из тушек освобождаемых объектов, у которых деструктор уже позвали.
guestinho 10.01.2017 23:33 # 0
Вот без гц могут возникать детерменированные, но такие охуительные паузы в программе, что любой го позавидует. Я как-то в одной программе сделал очередь для ненужных объектов и фоновый поток неспешно подчищающий эту очередь, потому что в определнных условиях программа могла надолго подвисать, 90% времени занимаясь удалением кучи таких объектов. Кажется это решение заслуживает собственного треда на говнокоде.
defecate-plusplus 11.01.2017 02:48 # 0
Если некая шняга гигабайтами плодила одноразовые объекты, то по принципам "нахуй raii"+"нахуй стандартный аллокатор, размещаем все новые объекты подряд в своей отдельно заранее выделенной области" можно было бы по окончанию операции, насравшей столько мусора, дропать всю область за раз (ну или возвращать ее в пул пустых). Заодно мифических проблем с дефрагментацией кучи было бы меньше.
Насколько мне известно, в гейдеве довольно распространенный подход, когда очередной уровень инициализируется.
guestinho 11.01.2017 03:08 # 0
bormand 11.01.2017 06:16 # 0
Ну т.е. виновато совсем не управление памятью. С гц было бы то же самое (т.к. тяжелую работу один хер надо выполнить).
roman-kashitsyn 11.01.2017 12:23 # 0
> тяжелую работу один хер надо выполнить
GC может такие вещи амортизировать, выполняя не всю работу сразу и уменьшая contention. Но поскольку делать в финализаторах "тяжёлую работу" — плохая идея, нужно всё равно пилить очередь (в жабе, к примеру, есть reference queue), которая будет потихоньку подчищать в одном потоке. Правда, в качестве платы за меньшие паузы, high water mark использования удяляемых в бэкграунде ресурсов может заметно подрасти.
defecate-plusplus 11.01.2017 09:15 # +1
- Потому что может.
Если у тебя там какая-то тяжелая работа - а как по мне тяжелая работа это пописать в базу или пообщаться с другими модулями/сервисами - то это совершенно точно не надо делать в деструкторе. Даже если там объект должен уведомить о своей кончине кучу мониторящих каких-то менеджеров - это не должно быть в деструкторе.
Если бы у тебя там на shared/weak ссылках был организован лайфтайм объекта, то вышенаписанное было бы самоочевидно - у тебя бы не получилось засунуть в деструктор тяжелой работы, т.к. это этап, когда уже поздно пить боржоми.
guestinho 11.01.2017 10:17 # 0
Схуяль? И тяжелая работа - это то, что заставляет 500к деструкторов отрабатывать заметное время.
> Если бы у тебя там на shared/weak ссылках был организован лайфтайм объекта, то вышенаписанное было бы самоочевидно - у тебя бы не получилось засунуть в деструктор тяжелой работы, т.к. это этап, когда уже поздно пить боржоми
Схуяли?
defecate-plusplus 11.01.2017 12:00 # +2
У деструктора нет никаких других результатов кроме корректной очистки, у него нет шансов наткнуться на неработающий или блокирующий внешний ресурс, т.к. ему некогда ждать и тем более делать второй заход. В деструкторе должно быть только то, что зависит от самого объекта и рантайма.
> shared/weak
Отличный пример, что деструктор не вызывается тобой, а только тогда, когда объект не нужен никому, не должен никому, и поэтому он спокойно умирает, не дергая больше ничего - он уже дёрнул все что нужно пока был живой (и оставался нужным кому-то).
huesto 11.01.2017 12:39 # 0
Погугли RAII.
> деструктор не вызывается тобой, а только тогда, когда объект не нужен никому, не должен никому, и поэтому он спокойно умирает, не дергая больше ничего
Ну это какие-то твои домыслы. Не знаю, что тебе на них ответить. В той программе те объекты управлялись как раз шаред пойнтером.
defecate-plusplus 11.01.2017 14:21 # +3
Приведи мне пример, что из бизнес-логики должен сделать твой объект, когда число ссылок на него достигло нуля и поэтому деструктор шаред птра вызвал его деструктор? Возможно ли там исключение или негативный результат бизнес-логики?
И пример, когда ты не можешь предположить более очевидное место, где эта бизнес-логика должна произойти - ведь счетчик ссылок не уменьшается просто так
Ведь
> когда 100500 клиентов одновременно отключались от сервера
.. это и есть то самое внешнее событие, которое происходит существенно до того, как ты в принципе захочешь вызвать деструктор - объект коннекшена живой и может заниматься бизнес-логикой (писать в базы, чистить вилкой и прочее) до посинения, с гарантией исполнения, с попытками, и только когда уже больше нечего делать в логике, освободить себя от связей с этим миром, и шаред птр его сам прибьет когда объект реально можно прибить
Подумай на досуге, как реализованы те же задачи на языках, где деструкторов вообще нет, а на финалайз никакой надежды. Про кота - это именно об этом. Потому что может.
guestinho 11.01.2017 14:33 # 0
roman-kashitsyn 11.01.2017 15:19 # +4
fixed
guestinho 11.01.2017 15:34 # +1
А если речь про потоки/корутины, то лучше прямо на стеке.
guestinho 11.01.2017 15:41 # 0
defecate-plusplus 11.01.2017 15:49 # +1
И никогда не жаловался на тяжелые деструкторы. Именно по той причине, что меня в последнюю очередь интересует, когда коннекшен или любой другой прикрытый шаред птр объект умрет.
Потому что его смерть = возврат памяти в кучу, все существенное я забрал с него сам в подходящий момент.
Ладно, /thread.
roman-kashitsyn 11.01.2017 12:10 # +1
Ну вот недавний пример из жизни (код был не мой, разумеется): попробуй реализовать бинарное небалансируемое дерево, которое хранит потомков в shared_ptr, а потом сделай ему 500 уровней, запасись попкорном и смотри, как переполняется стек при уничтожении корня.
> С гц было бы то же самое
Не совсем, см. пример выше. Различие в том, что GC обходит дерево объектов в ширину, а деструкторы — в глубину. Поэтому в языках с GC проще и более безболезненно создавать глубоко вложенные структуры данных.
defecate-plusplus 11.01.2017 12:26 # 0
А тут всего то воркэраунд над тем, что не подошли размеры стека, подходящие в 99.999% остальных случаях (кстати, лень проверить, но 500 не выглядит каким-то конским числом, просто поверю).
Переписав деструктор с дефолтного ты получишь те же миллисекунды выполнения и независимость от долгих внешних ресурсов.
roman-kashitsyn 11.01.2017 12:38 # 0
У нас обычно работает куча тредов, которые делают простые задачи. Поэтому дефолтные размеры стека на уровне килобайтов.
defecate-plusplus 11.01.2017 12:40 # 0
roman-kashitsyn 11.01.2017 12:46 # 0
?
defecate-plusplus 11.01.2017 12:50 # +1
Все, обхода достаточно - дальше деструкторы корня (в нем уже только 100 глубина лежит) и вектора отработают сами без переполнения стека.
roman-kashitsyn 11.01.2017 13:19 # 0
Откуда ты в деструкторе узнаешь, какая у тебя глубина? Проще уж выкинуть деструкторы нодов совсем и сделать так:
defecate-plusplus 11.01.2017 13:44 # +1
rotretS 10.01.2017 21:57 # 0
bormand 10.01.2017 21:58 # 0
> не будет скинут на диск
>> на чтение
rotretS 10.01.2017 21:59 # +1
barop 10.01.2017 22:06 # −2
bormand 10.01.2017 22:09 # 0
Потому что память - однородный ресурс. Эти 100 мегабайт или другие 100 мегабайт я держу - всем похуй. А файлы нужны конкретные.
barop 10.01.2017 22:18 # 0
rotretS 10.01.2017 22:09 # 0
bormand 10.01.2017 22:14 # 0
Длину не указал, на которую сравнивать.
rotretS 10.01.2017 22:15 # 0
bormand 10.01.2017 20:46 # 0
rotretS 10.01.2017 21:15 # 0
Лазарь-это визуальная среда, где компилер - fpc. Там всегда новые версии, а я скачивал недавно, месяц назад.
bormand 10.01.2017 21:17 # 0
guestinho 10.01.2017 23:36 # −3
rotretS 10.01.2017 23:42 # −1
,и вот, обязателно должен был прийти какой-то гомосексуалист и всё испортить...
Если честно, я ждал, что придёт Инканус - но, почему-то не пришёл.
guestinho 10.01.2017 23:47 # −2
А что если я и есть...
rotretS 10.01.2017 23:48 # +1
guestinho 10.01.2017 23:52 # −3
guestinho 11.01.2017 00:02 # −2
guestinho 11.01.2017 00:05 # −2
Dr_Stertor 11.01.2017 00:15 # 0
Романтика может и есть, спорить не буду, но взамен Вам гарантировано прохладное отношение товарищей, привыкших к тому, что новички зачастую выкидывают нелицеприятные номера.
guestinho 11.01.2017 00:16 # 0
Dr_Stertor 11.01.2017 00:17 # 0
1024-- 11.01.2017 02:06 # +1
barop 11.01.2017 00:16 # 0
Зачем тут дефис?
Dr_Stertor 11.01.2017 00:18 # 0
barop 11.01.2017 00:19 # 0
Dr_Stertor 11.01.2017 00:20 # 0
barop 11.01.2017 00:22 # 0
Dr_Stertor 11.01.2017 00:23 # 0
barop 11.01.2017 00:26 # +1
Тире длиннее минуса.
хуй большой а ландыш маленькиииий
Dr_Stertor 11.01.2017 00:28 # +2
примеры использования дефиса:
человек-оркестр, ковёр-самолёт, где-то, что-то, откуда-то....
barop 11.01.2017 00:31 # −2
--банан длинный, а яблоко нет
--Ответ неправильный. Спелый банан не бывает зеленым, а спелое яблоко бывает.
>>Тире - разделяет слова, а дефис - связывает.
Опять путаешь. Ох.
Dr_Stertor 11.01.2017 00:35 # +2
Опять путаешь. Ох.
Держи пруф с википедии:
Не следует путать дефис и тире. Дефис — орфографический знак, тире — пунктуационный. Кроме того, тире в русской типографике (но не в англоязычной), в отличие от дефиса, отбивается пробелами
barop 11.01.2017 00:41 # −1
>> Тире разделяет слова, а дефис - связывает.
Правильный от вики
>> Дефис — орфографический знак
guestinho 11.01.2017 00:19 # +1
barop 11.01.2017 00:19 # 0
Вот тире: "—"
guestinho 11.01.2017 00:30 # 0
barop 10.01.2017 23:48 # −3
Вот именно что в KOI, а уже 15 лет как KOI8-R не нужен
barop 10.01.2017 23:47 # −3
inkanus-gray 11.01.2017 00:24 # 0
barop 11.01.2017 00:25 # 0
Кстати, я в детстве писал писал на Trubo Pascal 7.0 и говорил что пишут на паскале. А ведь это была неправда: в классическом паскале не было объектов.
inkanus-gray 11.01.2017 00:31 # 0
Надо же на чём-то писать Total Commander!
barop 11.01.2017 00:34 # 0
* https://wiki.mozilla.org/Ports/os2
* http://www.parser.ru/
>> PascalABC.NET,
Слышал, что в Питере на нём детей учат, потому что курсы по паскалю с 1996 года не сильно поменялись.
inkanus-gray 11.01.2017 00:38 # 0
barop 11.01.2017 00:39 # 0
На них просто такая уже кодовая база что выкинуть, переписать и переучить будет стоить охулион долларов?
defecate-plusplus 11.01.2017 02:35 # +1
Dr_Stertor 11.01.2017 00:43 # +1
Хромой аналог Delphi 8, на костылях.
barop 11.01.2017 00:45 # −1
huge_cock 11.01.2017 13:28 # 0
huesto 11.01.2017 13:38 # 0
rotretS 10.01.2017 23:50 # 0
Они горят, словно капельки жизни на фартуке студента-хирурга.