Как стать автором
Обновить
3
0

Программист

Отправить сообщение

Я считаю, делать гц "универсальным аллокатором" для всех new смысла нет (тогда лучше выбрать другой язык), но имеет смысл создавать определенные высокоуровневые категории объектов через гц (например, игровые сущности). При этом созданные через гц-аллокатор объекты не должны торчать наружу указателями вообще - а иметь свой умный указатель, позволяющий отгородить внешнюю логику от доступа по висячей ссылке. В c++/cli похожая схема, где можно создавать объекты как через new, так и через gcnew.

В своем проекте я решал эту проблему кастомным полуумным указателем: уничтожение вызывается только вручную вызовом метода destroy на самом указателе, но все копии этого указателя впоследствии разыменовываются в nullptr (избегаем висячих ссылок). Ну и, собственно, как и вызов delete на nullptr безопасен, так и destroy внутри другого destroy не будет делать ничего. А вообще, желательно избегать использование деструктора и по возможности создавать объекты через фабричный метод и задавать там функцию удаления. Таким образом решается проблема возможного вызова виртуальных методов в конструкторе и деструкторе.

Учитывая, что перебежчики сами добавляют себя в список на депортацию, предложенное решение происходит за O(n) и выглядит универсальным. При копировании же могут возникать частные случаи - копирование может быть дорогим (не POD?), проблема передачи владения объектов в полях скопированного объекта, копирование объекта запрещено или чёрт знает что ещё. В любом случае перемещение указателя внутри умного указателя будет быстрее. Если же объект легковесный, то и пул для него заводить смысла нет.

Ну, даже если отложить попытки решить данную проблему, нужно хотя бы иметь возможность отслеживать существование островов хотя бы в debug-сборке, ведь случайно создать острова очень просто, а память не бесконечная. Иначе выйдет так, что сборщик добавит новый класс проблем, куда посерьёзнее чем те, которые он призван решить.

Upd: Еще есть проблема с многопоточностью - если объект передаётся в другой поток, то освобождение может произойти в неподконтрольном потоке, что еще сильнее все усложняет. Деструкторы и неконтролируемое время уничтожения - само по себе создаёт проблему. Как способ решения - все вызовы деструкторов умных указателей должны происходить в определённый этап цикла потока. Да, очерёдность вызовов деструкторов не гарантируется, но зато гарантируется, что это не произойдёт случайно в неподходящий момент. В своём движке у меня был самописный таск-менеджер как класс-обёртка над потоком, и он работал в паре с объектными пулами. Чтобы избежать синхронизации, пулы были thread_local. И постоянно возникал кейс, когда объекты передавались в другой поток. После использования в другом потоке объекты нужно было уничтожать, но утилизировать в пул чужого потока - не вариант, иначе пул первого потока будет аллоцировать всё новые и новые, а поток-получатель только собирать "перебежчиков". То есть, в качестве механизма "департации" в родной поток объекты помещались в специальный список, отдельный список на каждый поток. И тут на помощь приходит тот самый кастомный таск-менеджер: в конце цикла он проверяет все списки "депортируемых" и пачками за один заход возвращает все объекты в их родной поток через специальный таск. Родной поток же в свою очередь в начале цикла подбирал всех "депортированных" и вызывал деструкторы. Звучит сумбурно, прошу простить. Может моя идея реализации кому-то чем-то поможет.

А что насчёт циклических ссылок и островов памяти? Признаюсь, код смотрел по диагонали, но в тексте упоминания решения данной проблемы не нашел.

А ещё зелёный свет светофора у них до сих пор называется 青い. А всё потому, что раньше в японских светофорах использовался именно голубой цвет (до сих пор иногда можно встретить). Тем не менее, никто не говорит 緑信号. Вот именно на таких случаях языки со временем обрастают всякими "нелогичностями" и исключениями из правил - "большинство привыкло" ⇒ "исторически сложилось".

UPD: Раз уж упомянул - в японских шрифтах обильно используются значки для замены некоторых слов. Напечатав слово 右 ("правый", "вправо") IME-ввод (и ему подобные на мобилках) тебе также предлагает готовые значки →⇒☞➡ (вот откуда появились эмодзи). Для меня - довольно удобная фича, особенно наличие стрелок

Как это выглядит:

А что за варнинги игнорируются - компилятора или статического анализатора?

Компилятора. Как ни странно, сотни варнингов компиляции "кастую знаковый в беззнаковый" в статическом анализаторе заглушены заранее (анализатор запускается у другой команды, я не знаю результата своих правок)

Что значит они исправлены (о чем пишется в отчете)?

Надо либо исправить (чаще всего - заглушить возвращаемое функцией значение через приведение к (void)) и описать, почему исправил так а не, например, добавил проверку на возвращаемое значение, либо заглушить специальным блоком комментария, который видит анализатор. К слову, я вообще в этом проекте - мимокрокодил, и без расспрашивания разных людей понятия не имею, что функции в коде очередного драйвера делать, если сделать "по уму" и добавить ветку с обработкой ошибки

Почему их можно ассертами починить?

Часто бывает так, что возвращаемый функцией код ошибки в принципе не должен быть ошибкой, либо логикой программы не предусмотрен ошибочный кейс - так или иначе, стоит влепить проверку кода ошибки хотя бы на уровне ассерта. И внутренний перфекционист спокоен, и анализатор замолчит

Насчет неиспользуемых файлов - почему их нельзя совсем удалить?

Потому что эти файлы исходников автогенерируются (удалять/править бессмысленно) либо еще могут пригодиться (проект еще в процессе разработки).

Кстати, в японских аутсорс-компаниях это скорее правило, чем исключение. Тут есть такое явление - "заказчик - бог и всегда прав". Все это пришло из сферы услуг и проникло повсюду. И местные тимлиды вместе со стажем впитывают в себя то, как надо угодить "букве заказа", а не ее "духу". Тут принято все решать "в лоб". Попробуй убедить тимлида, что даже в мире эмбеддед стоит использовать ассерты вместо игнорирования тысяч варнингов; если используется магический указатель в неизвестность - выделите ему хотя бы именованную константу; что клиническая боязнь mallocа - не оправдание для отсутствия архитектуры и т.д. А потом когда этот зоопарк заказчик требует прогнать через статический анализатор, тимлид требует с тебя составить кучу экселек, составленных по стандартам крупных корпораций с максимально переусложненной бюрократической частью, где должно быть пересказано текстом где, почему исправлен каждый из нескольких тысяч варнингов, как, кем исправлен, кем и когда проведено ревью этих исправлений, чтобы в глазах заказчика выглядеть солидной фирмой. И вишенка на торте - для чистоты отчета "на всякий случай" удалить из проекта и с файловой системы все неиспользуемые файлы (сиди парси логи линкера о неиспользуемых символах, составляй списки файлов и пиши утилиту удаления всех этих файлов "на время прогона анализатора", так как в будущем это нужно будет повторять снова).Уже половина успеха, если вообще разрешили для автоматизации этого процесса такую утилиту написать, а не "полировать тарелки" руками. И все это уже тимлид пообещал заказчикам сделать до завтра... Простите, наболело.

Подскажите, а зачем нужно две версии геттера, если константного достаточно? Точнее, существование неконстантного геттера автоматически ломает const-correctness, разве нет? Что-то вроде "гарантирую, что сам экземпляр класса CImageStorage не изменится, но если очень хочется, то можно"? Либо наоборот - если возвращаемый объект может быть изменен, то оставить только не-const версию? Как я понимаю, QPixmap& getTiles() const - не вариант? То есть, я чуйкой чую, что вы написали правильно, просто не хочу следовать таким практикам вслепую, хочется понимания.

Это звучит примерно как хитрый план родителей "сына, только ты можешь так хорошо вымыть посуду! Мы гордимся тобой! Никто не справится с этим лучше тебя!"

Хочу заметить, часть удобств при работе действительно обеспечивается IDE в определенных деталях, которые мы упускаем из виду. Вот как раз мне вспомнился пример, применительный к статье: в визуал студии в сишарпе очень выгодно использовать перечисления вместо флагов благодаря фиче интеллисенса: как только ты переходишь к указанию аргумента перечисления, тип перечисления сразу подставляется в списке, и ты сразу же видишь все варианты. А вот в интеллисенсе c++ той же визуал студии почему-то так не работает: приходится помнить название конкретного энума (почему-то оно само интеллисенсом не подставляется), и тут уже использование перечислений в качестве флагов становится чуть менее удобно из-за необходимости переключать голову. Извиняюсь за сумбур, на словах такое сложно объяснить

А я бы ответил что-то вроде «хорошо/плохо» — исключительно субъективная оценка, и если бы у объекта «карандаш» был бы метод узнать эту характеристику, то в качестве первого агрумента такой функции я бы передавал указатель на переменную базового класса «разумный субъект» )
Из игр схожего жанра и насыщенности по незнакомым мне английским словам могу отметить Europa Universalis 4
А бывает так, что даже «с ключом в руке» — тревожность не уходит. Вот смотришь ты на вытащенный ключ в руке, ясно помнишь, как пару секунд назад стопроцентно закрыл дверь (и что важно — не на автомате, а осознанно), и всё равно НАДО ещё раз подёргать ручку…
У вертикальных мышек с двойным нажатием как раз всё ещё хуже — если у обычной нажатие направлено «в стол», то у вертикальных — вбок. Мне самому пришлось потратить немало времени на то, чтобы гарантировать двойные нажатия без смещения курсора
Недавно писал по работе кастомный контрол для ввода IP-адреса (как просили заказчики, «чтобы как в Windows в свойствах интернет-подключения работало где ручками можно забивать адрес»), и там для первого октета есть ограничение на ввод 1-223. Так что RFC не RFC, а важно узнать, для какой задачи парсинг будет применяться.

Бонус: при исследовании поведения этого самого контрола в окне свойств подключения обнаружил баг: через копипаст в октет можно вставить число гораздо длиннее ожидаемого.
・зачем париться с инклюдами? Создайте один мега-header и заинклюдьте в него всё, что может потенциально пригодиться! И в самое начало не забудьте добавить
#include <windows.h>
и
using namespace std;
чтобы два раза не вставать!
Это, скорее, вариант быстрого return, чья область действия ограничена одним блоком do {} while вместо всей функции. Причин использования может быть несколько: может быть невыгодно выделять блок с do {} while в отдельную функцию (например, придется передавать слишком много локальных переменных в эту самую функцию), избавление от дублирования кода — иными словами, существенно сокращает количество кода с повышением удобочитаемости.
А знаете, что самое забавное? Благодаря IME-вводу (и его аналогам на смартфонах) где ты печатаешь текст латиницей и он сам предлагает варианты на иероглифах — я как-то поймал себя на мысли, что мне на японском проще печатать текст, чем его читать. С алфавитными языками-то обычно всё наоборот…
как и на язык(ехал с нулевым японским)

А вот это — самый главный фактор, как по мне. Как бы нас ни убеждали в обратном в описании вакансии. Но сильно зависит от фирмы…

Информация

В рейтинге
5 243-й
Откуда
Нагоиа, Айти, Япония
Зарегистрирован
Активность