Pull to refresh

Comments 10

Тут я напоролся на особенность IAR ARM, а именно то, что он инициализирует статические переменные два раза, в начале программы и непосредственно при входе в main

Быть такого не может. Статические переменные инициализируются один раз. Там на задворках создается флажок в ОЗУ, при следующей инициализации этот флажоки проверяется и повторной инициализации не происходит. Синглтон Майерса инициализируется при первом обращении, по месту. С мейном это вообще не связано. Где вызвали, там и проинициализировалось. А вот глобальные статические переменные инициализируются до main. Если все сделать по умолчанию в IAR вызывается его функция инициализации глобальных переменных. Можно эту инициализацию пропустить, например, если переопределить функцию _low_level_init и вернуть из нее 0, инициализация глобальных переменных пропускается.

С вами мне спорить трудно, знаю по вашим публикациям что вы очень давно в IAR работаете.
Я лишь описал то, что выдал мне отладчик при беглом просмотре, возможно я не так понял и вы правы.
Ладно virtual, но зачем же тащить в микроконтроллер std::map из стандартной бибилотеки, тем более, что номера портов нумеруются числами? Можно обойтись простым массивом, ну или списком наконец.
Просто пробую, эксперементирую, сравниваю результирующий код. А почему нет?
Я вижу две причины не использовать STL.
1. STL занимает много памяти
2. STL везде, где возможно, использует динамическую память.
По моим наблюдениям на основе компилятора IAR
Использование хотя бы одного «new» сильно увеличивает проект, сильнее чем использование хотя бы одного malloc.

Динамическая память имеет обыкновение заканчиваться, что приводит либо к exception, либо к возврату null. Включение exceptions в ембедед — это еще большее разбухание кода. Отключение exceptions — будь добр, отрабатывать все неудачные попытки выделения памяти, причем выделения часто бывают неявными, например, при использовании лямбд.

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

Так как обычно куча является односвязным списком (зависит от компилятора и настроек), то выделение динамической памяти не детерминировано по времени. Это может иметь значение в жестком рилтайме. Т.е. первый байт выделится за 1 наносекунду, а 10001 байт может выделиться за 1 микросекунду.
Спасибо за разъяснение!
Я одно время вообще кучу не использовал в проектах под embedded, сейчас сталкиваюсь с большими проектами, где куча используется.

Вообще, я для себя рассудил так. У меня прошивка без использования кучи под домашние проекты занимает не более 10-20 кБайт. На всех используемых мною камнях памяти от 128 до 512 кБайт. Почему не пожертвовать ей, если это улучшит переносимость и гибкость кода.

Это лишь моё мнение касательно моих проектов, оно может измениться. Повторюсь, ещё совсем недавно я был противником использование кучи в МК для несложных проектов.

Сильное кунг-фу, однако ничего необычного не увидел.
Зачем в hw процедурах приёма/отправки bool res, если он всегда false?

Осталось от прототипов, надо бы убрать.
Решительно поддерживаю автора в стремлении использовать современные плюсы в мк. Но дабы сохранить коллегам автора и ревьюерам его кода зубную эмаль, неизбежно страдающую от зубовного скрежета, когда в проектах под мк они видят «virtual bool init(uint32_t val)», не менее настоятельно советую автору оперативно проштудировать MUST READ минимум:
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 раз с виртуальными функциями. Мой опыт разбора дизамблера и некоторые статьи говорят о другом.

И все же сейчас, я предпочитаю статический полиморфизм динамическому при написании универсальных кода.

Sign up to leave a comment.

Articles