Comments 10
Тут я напоролся на особенность IAR ARM, а именно то, что он инициализирует статические переменные два раза, в начале программы и непосредственно при входе в main
Быть такого не может. Статические переменные инициализируются один раз. Там на задворках создается флажок в ОЗУ, при следующей инициализации этот флажоки проверяется и повторной инициализации не происходит. Синглтон Майерса инициализируется при первом обращении, по месту. С мейном это вообще не связано. Где вызвали, там и проинициализировалось. А вот глобальные статические переменные инициализируются до main. Если все сделать по умолчанию в IAR вызывается его функция инициализации глобальных переменных. Можно эту инициализацию пропустить, например, если переопределить функцию _low_level_init и вернуть из нее 0, инициализация глобальных переменных пропускается.
1. STL занимает много памяти
2. STL везде, где возможно, использует динамическую память.
По моим наблюдениям на основе компилятора IAR
Использование хотя бы одного «new» сильно увеличивает проект, сильнее чем использование хотя бы одного malloc.
Динамическая память имеет обыкновение заканчиваться, что приводит либо к exception, либо к возврату null. Включение exceptions в ембедед — это еще большее разбухание кода. Отключение exceptions — будь добр, отрабатывать все неудачные попытки выделения памяти, причем выделения часто бывают неявными, например, при использовании лямбд.
Динамическая память может фрагментироваться. При первом запуске выделение может произойти успешно, а через год работы программы из-за фрагментации кучи память не выделится.
Так как обычно куча является односвязным списком (зависит от компилятора и настроек), то выделение динамической памяти не детерминировано по времени. Это может иметь значение в жестком рилтайме. Т.е. первый байт выделится за 1 наносекунду, а 10001 байт может выделиться за 1 микросекунду.
Я одно время вообще кучу не использовал в проектах под embedded, сейчас сталкиваюсь с большими проектами, где куча используется.
Вообще, я для себя рассудил так. У меня прошивка без использования кучи под домашние проекты занимает не более 10-20 кБайт. На всех используемых мною камнях памяти от 128 до 512 кБайт. Почему не пожертвовать ей, если это улучшит переносимость и гибкость кода.
Это лишь моё мнение касательно моих проектов, оно может измениться. Повторюсь, ещё совсем недавно я был противником использование кучи в МК для несложных проектов.
Сильное кунг-фу, однако ничего необычного не увидел.
Зачем в hw процедурах приёма/отправки bool res, если он всегда false?
a) Б. Страуструп «Программирование: принципы и практика использования С++» глава 25;
б) С. Мейерс «Эффективное использование С++ во встроенных системах»
с) Alex Robenko «Practical guide to bare metal c++»
плюс полезно будет посмотреть отличный доклад Карины Дорожкиной с конференции CPP Russia 2019, www.youtube.com/watch?v=Yv4nMocX78Q
Уверен, это даст автору отсутствующее сейчас (на мой взгляд) важное понимание, что у с++ «под капотом» в части использования в ембеде, и как правильно с этим жить. И в итоге поможет ему сойти с ошибочной тропы, которая привела его к написанию этого материала.
PS. Касаемо virtual. Вызов виртуальной функции примерно в 10 раз медленнее обычной (плюс оверхед на хранение таблицы указателей). Смотрим тесты, например здесь (взято у Ф. Пикуса ) quick-bench.com/q/42iKBatMiDjQtRHIcIWb3hLgbU8
Успехов!
Добрый день, cпасибо за комментарий!
Я полностью поддерживаю вашу точку зрения. Как видите, статья была написана 2 года назад и сейчас я считаю такой подход ошибочным. Честно говоря, я думаю, что это был дерьмовый код со всех сторон.
Теперь я перешел на что-то вроде этого: https://github.com/isobchuk/cpp_register (просто пример).
Однако я не согласен с замедлением в 10 раз с виртуальными функциями. Мой опыт разбора дизамблера и некоторые статьи говорят о другом.
И все же сейчас, я предпочитаю статический полиморфизм динамическому при написании универсальных кода.
Попытка использовать современный C++ и паттерны проектирования для программирования микроконтроллеров