- 1
Знаете ли Вы, что в FreePascal блоки try..finally/except не работают в контексте DLL?
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
−18
Знаете ли Вы, что в FreePascal блоки try..finally/except не работают в контексте DLL?
Не ловят исключения или вообще не компилятся?
З.Ы. Ну и исключение брошено из той же самой дллки, или из функции какой-то другой дллки или самого экзешника?
Лол, т.е. dll'ка даже свои собственные исключения не видит в упор?
З.Ы. Попробуй на динамический рантайм переключиться, если оно умеет (и в экзешнике и в дллке само собой).
Приложение так или иначе всё равно грузит *.bpl-пакет в память, значит, дело не в выйгрыше в размере занимаемой памяти. А в чем тогда?
В общем менеджере памяти и общей инфе о классах. Все дллки и экзешка с общим рантаймом как-бы сливаются в одно целое. Можно спокойно юзать ООП и прочие ништяки на всю катушку.
Wow. Но это же замечательно. Можно запилить свое ООП с блэк-джэком и шлюхами.
В общем-то да.
Хз, ошибка это или нет. Система ведь всё равно подчистит. Но в своих прогах я очень щепетильно отношусь к утечкам.
Ну это же не утечка, просто объект, закешированный в глобалку. Многие либы этим страдают.
З.Ы. "Любой static" всё-таки не лежит в куче.
Плохо когда они плодятся, когда через N часов работы у тебя куча такая что на тебя ООМКиллер поглядывает
Здесь другой случай. Деструктор не вызывается вовсе и память освобождает сама система, в момент закрытия приложения.
Т.е. обеспечивается "резиновый" размер памяти, но это даётся ценой размещения в ней висячих объектов?
Речь о том, что сборщик мусора должен быть активен вплоть до завершения работы проги, а сам при этом утечет.
Не поможешь?
Я так понимаю, что идёт обмен шила на мыло.
Что представляет собой GC? Наверняка, это какой-то глобальный объект для подчищаемой проги, который управляет ее памятью. Если его инстанс создаётся каждый раз для каждой проги, по завершению ее работы он "утекает" - т.е., он же не может деаллоцировать сам себя - его прихлопывает система.
Да и хуй с ним, он ничтожно мал по сравнению с тем, что он успевает почистить за свою жизнь.
З.Ы. Утечки мало кого беспокоят после смерти. Главное - чтобы они не мешали при жизни :)
Почему шило на мыло то? Ну да, виртуальная машина занимает память. При выключении машины эта память освобождаеца.
Что плохого?
Дополнительный поток, который чистит память своего же процесса?
Ну точнее это конечно зависит от реализации. Думаю что ты имеешь право реализовать так, как тебе удобно, но вот JVM это так, думаю то и в .NET так же.
Где, по твоему, лежит синглтон со своими полями?
Это норма, и такое вообще часто используется. Для быстродействия в том числе: если программа работает недолго и вызывается часто (что-то типа grep или cat) то нефиг ей перед завершением в куче рыться, деаллоцируя заведомо обречённые на гибель объекты.
Т.е. GC - говно, т.к. освобождает её в самый-самый последний момент, когда аллокатор вот-вот обломится?
ладно, я понял разницу: файл может быть нужен конкретный, а память не важно какая: главное, чтобы была
Тормозной, неполноценный, ненадёжный, ненужный.
То ли дело машина Тьюринга с бесконечной лентой.
Лента - медленная хуйня с последовательным доступом. То ли дело бесконечная память...
З.Ы. Но как эту бесконечную память адресовать?
С помощью регистра бесконечного размера конечно же
Разница в использовании по сравнению с GC только в невозможности выпилить isle of isolation, и потому нужно было понимать в какую сторону можно делать strong ref, а в какую -- нет, что порождало говнопаттерны типа "strong weak dance", зато никто не широёбился в фоне и не искал пути к объекту из стеков потока и пермгена. Может быть потому айфон дольше держит зарядку, чем андроидные девайсы?;)
Но если совсем по честному, то я от ручного управления памятью не умирал: надо было быть очень внимательным
Не знаю, как в ObjC, но в йеху он меня не впечатлил.
http://govnokod.ru/19104
Если у тебя A ссылается на B, а B на A то одна из ссылок должна быть weak (тоесть на каунтинг не влиять и обнуляца).
В твоем примере тоже самое только A и B у тебя инстансы одного класс.
Кстати, в UIKit есть очень четкие конвенции на этот счет: контроллер имеет ссылки на свои элементы, а они на него weak, и потому когда на контроллер никто не ссылается то его можно уебать, и его потомки дадут дуба вместе с ним. А буть ссылки жесткие -- ты бы их никогда бы не удалил
Вот тут p ссылается на p0: var p = R(a : p0)
А вот тут p0 на p: p0._a = p
Обе ссылки стронговые. Objc мог смело сделать memory leak, а сырой стриж запутался и наступил себе на шнурки.
В любом случае ты НЕ прав: ты сделал некрасиво.
> if leak
> test(noLeak, leak: false)
Я тебя верно понял? У меня нет ябла просто чтобы собрать, а из твоих комментов я сделал именно такой вывод.
В общем я согласен с тем, что свифт повел себя как говно. Но это вопрос не к RC а его реализации.
Было бы здорово, если бы reference cycle был бы объявлен UB
Развалится же сразу.
Все кошерненько соберется и уйдет в помойку.
В Objc посылка сообщения нилу валидна, думаю что и в свифте тоже.
Будет точно то же самое, что и в случае с leak:false.
Угу, даже не успев построиться (что я и имел в виду под развалится). Как я тебе вилкой на виках буду список строить?
З.Ы. Или ты только про последний замыкающий элемент?
Ну тут, в общем случае, задача хреновая. Можно разве что заменить рекурсию очередью. А чтобы не выделять память при освобождении памяти - строить эту очередь из тушек освобождаемых объектов, у которых деструктор уже позвали.
Вот без гц могут возникать детерменированные, но такие охуительные паузы в программе, что любой го позавидует. Я как-то в одной программе сделал очередь для ненужных объектов и фоновый поток неспешно подчищающий эту очередь, потому что в определнных условиях программа могла надолго подвисать, 90% времени занимаясь удалением кучи таких объектов. Кажется это решение заслуживает собственного треда на говнокоде.
Если некая шняга гигабайтами плодила одноразовые объекты, то по принципам "нахуй raii"+"нахуй стандартный аллокатор, размещаем все новые объекты подряд в своей отдельно заранее выделенной области" можно было бы по окончанию операции, насравшей столько мусора, дропать всю область за раз (ну или возвращать ее в пул пустых). Заодно мифических проблем с дефрагментацией кучи было бы меньше.
Насколько мне известно, в гейдеве довольно распространенный подход, когда очередной уровень инициализируется.
Ну т.е. виновато совсем не управление памятью. С гц было бы то же самое (т.к. тяжелую работу один хер надо выполнить).
> тяжелую работу один хер надо выполнить
GC может такие вещи амортизировать, выполняя не всю работу сразу и уменьшая contention. Но поскольку делать в финализаторах "тяжёлую работу" — плохая идея, нужно всё равно пилить очередь (в жабе, к примеру, есть reference queue), которая будет потихоньку подчищать в одном потоке. Правда, в качестве платы за меньшие паузы, high water mark использования удяляемых в бэкграунде ресурсов может заметно подрасти.
- Потому что может.
Если у тебя там какая-то тяжелая работа - а как по мне тяжелая работа это пописать в базу или пообщаться с другими модулями/сервисами - то это совершенно точно не надо делать в деструкторе. Даже если там объект должен уведомить о своей кончине кучу мониторящих каких-то менеджеров - это не должно быть в деструкторе.
Если бы у тебя там на shared/weak ссылках был организован лайфтайм объекта, то вышенаписанное было бы самоочевидно - у тебя бы не получилось засунуть в деструктор тяжелой работы, т.к. это этап, когда уже поздно пить боржоми.
Схуяль? И тяжелая работа - это то, что заставляет 500к деструкторов отрабатывать заметное время.
> Если бы у тебя там на shared/weak ссылках был организован лайфтайм объекта, то вышенаписанное было бы самоочевидно - у тебя бы не получилось засунуть в деструктор тяжелой работы, т.к. это этап, когда уже поздно пить боржоми
Схуяли?
У деструктора нет никаких других результатов кроме корректной очистки, у него нет шансов наткнуться на неработающий или блокирующий внешний ресурс, т.к. ему некогда ждать и тем более делать второй заход. В деструкторе должно быть только то, что зависит от самого объекта и рантайма.
> shared/weak
Отличный пример, что деструктор не вызывается тобой, а только тогда, когда объект не нужен никому, не должен никому, и поэтому он спокойно умирает, не дергая больше ничего - он уже дёрнул все что нужно пока был живой (и оставался нужным кому-то).
Погугли RAII.
> деструктор не вызывается тобой, а только тогда, когда объект не нужен никому, не должен никому, и поэтому он спокойно умирает, не дергая больше ничего
Ну это какие-то твои домыслы. Не знаю, что тебе на них ответить. В той программе те объекты управлялись как раз шаред пойнтером.
Приведи мне пример, что из бизнес-логики должен сделать твой объект, когда число ссылок на него достигло нуля и поэтому деструктор шаред птра вызвал его деструктор? Возможно ли там исключение или негативный результат бизнес-логики?
И пример, когда ты не можешь предположить более очевидное место, где эта бизнес-логика должна произойти - ведь счетчик ссылок не уменьшается просто так
Ведь
> когда 100500 клиентов одновременно отключались от сервера
.. это и есть то самое внешнее событие, которое происходит существенно до того, как ты в принципе захочешь вызвать деструктор - объект коннекшена живой и может заниматься бизнес-логикой (писать в базы, чистить вилкой и прочее) до посинения, с гарантией исполнения, с попытками, и только когда уже больше нечего делать в логике, освободить себя от связей с этим миром, и шаред птр его сам прибьет когда объект реально можно прибить
Подумай на досуге, как реализованы те же задачи на языках, где деструкторов вообще нет, а на финалайз никакой надежды. Про кота - это именно об этом. Потому что может.
fixed
А если речь про потоки/корутины, то лучше прямо на стеке.
И никогда не жаловался на тяжелые деструкторы. Именно по той причине, что меня в последнюю очередь интересует, когда коннекшен или любой другой прикрытый шаред птр объект умрет.
Потому что его смерть = возврат памяти в кучу, все существенное я забрал с него сам в подходящий момент.
Ладно, /thread.
Ну вот недавний пример из жизни (код был не мой, разумеется): попробуй реализовать бинарное небалансируемое дерево, которое хранит потомков в shared_ptr, а потом сделай ему 500 уровней, запасись попкорном и смотри, как переполняется стек при уничтожении корня.
> С гц было бы то же самое
Не совсем, см. пример выше. Различие в том, что GC обходит дерево объектов в ширину, а деструкторы — в глубину. Поэтому в языках с GC проще и более безболезненно создавать глубоко вложенные структуры данных.
А тут всего то воркэраунд над тем, что не подошли размеры стека, подходящие в 99.999% остальных случаях (кстати, лень проверить, но 500 не выглядит каким-то конским числом, просто поверю).
Переписав деструктор с дефолтного ты получишь те же миллисекунды выполнения и независимость от долгих внешних ресурсов.
У нас обычно работает куча тредов, которые делают простые задачи. Поэтому дефолтные размеры стека на уровне килобайтов.
?
Все, обхода достаточно - дальше деструкторы корня (в нем уже только 100 глубина лежит) и вектора отработают сами без переполнения стека.
Откуда ты в деструкторе узнаешь, какая у тебя глубина? Проще уж выкинуть деструкторы нодов совсем и сделать так:
> не будет скинут на диск
>> на чтение
Потому что память - однородный ресурс. Эти 100 мегабайт или другие 100 мегабайт я держу - всем похуй. А файлы нужны конкретные.
Длину не указал, на которую сравнивать.
Лазарь-это визуальная среда, где компилер - fpc. Там всегда новые версии, а я скачивал недавно, месяц назад.
,и вот, обязателно должен был прийти какой-то гомосексуалист и всё испортить...
Если честно, я ждал, что придёт Инканус - но, почему-то не пришёл.
А что если я и есть...
Романтика может и есть, спорить не буду, но взамен Вам гарантировано прохладное отношение товарищей, привыкших к тому, что новички зачастую выкидывают нелицеприятные номера.
Зачем тут дефис?
Тире длиннее минуса.
хуй большой а ландыш маленькиииий
примеры использования дефиса:
человек-оркестр, ковёр-самолёт, где-то, что-то, откуда-то....
--банан длинный, а яблоко нет
--Ответ неправильный. Спелый банан не бывает зеленым, а спелое яблоко бывает.
>>Тире - разделяет слова, а дефис - связывает.
Опять путаешь. Ох.
Опять путаешь. Ох.
Держи пруф с википедии:
Не следует путать дефис и тире. Дефис — орфографический знак, тире — пунктуационный. Кроме того, тире в русской типографике (но не в англоязычной), в отличие от дефиса, отбивается пробелами
>> Тире разделяет слова, а дефис - связывает.
Правильный от вики
>> Дефис — орфографический знак
Вот тире: "—"
Вот именно что в KOI, а уже 15 лет как KOI8-R не нужен
Кстати, я в детстве писал писал на Trubo Pascal 7.0 и говорил что пишут на паскале. А ведь это была неправда: в классическом паскале не было объектов.
Надо же на чём-то писать Total Commander!
* https://wiki.mozilla.org/Ports/os2
* http://www.parser.ru/
>> PascalABC.NET,
Слышал, что в Питере на нём детей учат, потому что курсы по паскалю с 1996 года не сильно поменялись.
На них просто такая уже кодовая база что выкинуть, переписать и переучить будет стоить охулион долларов?
Хромой аналог Delphi 8, на костылях.
Они горят, словно капельки жизни на фартуке студента-хирурга.