Использование C++ во встроенных системах

Я узнал, что, поскольку я использую формы Gatsbyjs и Gatsby + Netlify = javascript, мне нужно было добавить еще одну input type="hidden" в мою форму:

Документация для этого была не сразу Ясно, но ниже приведены некоторые ссылки, которые обращаются к этому:

25
задан JeffV 23 September 2008 в 13:24
поделиться

17 ответов

RTTI и Обработка исключений:

  • размер кода Увеличений
  • выполнение Уменьшений
  • Может часто заменяться более дешевыми механизмами или лучшей разработкой программного обеспечения.

Шаблоны:

  • быть осторожным с ними, если размер кода является проблемой. Если Ваш целевой ЦП имеет не или только очень крошечный Г-nstruction кэш, это может уменьшить производительность также. (шаблоны имеют тенденцию чрезмерно увеличивать размер кода, если используется без ухода). Otoh умное метапрограммирование может уменьшить размер кода также. Нет никакого ясного ответа на его.

Виртуальные функции и наследование:

  • Они хорошо для меня. Я пишу почти весь свой встроенный код в C. Это не мешает мне использовать таблицы указателя функции для имитации виртуальных функций. Они никогда не становились проблемой производительности.
19
ответ дан 28 November 2019 в 18:22
поделиться

Обратите внимание, что стоимость исключений зависит от вашего кода. В одном профилированном приложении (относительно небольшое на ARM968) поддержка исключений добавила 2% к времени выполнения, а размер кода был увеличен на 9,5 КБ. В этом приложении исключения создавались только в том случае, если произошло что-то серьезно плохое, то есть никогда не происходило на практике, из-за чего время выполнения было очень низким

.
0
ответ дан 28 November 2019 в 18:22
поделиться

Одна конкретная проблема, которая удивила меня ATMega GCC 3.something: когда я добавил виртуальную функцию тлеющих углей к одному из моих классов, я должен был добавить виртуальный деструктор. В той точке компоновщик попросил оператор удалять (пусто *). Я понятия не имею, почему это происходит, и добавление пустого определения для того оператора slolved проблема.

0
ответ дан 28 November 2019 в 18:22
поделиться

Убедитесь, что вы знаете, какие функции поддерживаются компилятором для вашей встроенной платформы, а также убедитесь, что вы знаете особенности вашей платформы. Например, компилятор CodeComposer от TI не выполняет автоматическое создание шаблонов. В результате, если вы хотите использовать сортировку STL, вам нужно вручную создать пять разных вещей. Он также не поддерживает потоки.

Другим примером является то, что вы можете использовать чип DSP, который не имеет аппаратной поддержки для операций с плавающей запятой. Это означает, что каждый раз, когда вы используете float или double, вы оплачиваете стоимость вызова функции.

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

0
ответ дан 28 November 2019 в 18:22
поделиться

Для встроенных систем Вы преимущественно захотите избежать вещей, которые имеют определенную аварийную стоимость во время выполнения. Некоторые примеры: исключения, и RTTI (для включения dynamic_cast и идентификатор типа ).

0
ответ дан 28 November 2019 в 18:22
поделиться

Если вы используете среду разработки, нацеленную на встраиваемую разработку, или определенную встроенную систему, она должна была уже ограничить некоторые варианты для вас. В зависимости от возможностей ресурса вашей цели, он отключит некоторые из вышеупомянутых элементов (RTTI, исключения и т. Д.). Это более простой путь, вместо того, чтобы помнить о том, что приведет к увеличению размера или требований к памяти (хотя, в любом случае, вы должны узнать это мысленно).

0
ответ дан 28 November 2019 в 18:22
поделиться

Используя и компилятор ARM GCC и собственный SDT ARM у меня были бы следующие комментарии:

  • ARM SDT производит более трудный, более быстрый код, но очень дорог (> Eur5k на рабочее место!). В моем предыдущем задании мы использовали этот компилятор, и это было в порядке.

  • инструменты GCC ARM работают очень хорошо, хотя и это - то, что я использую на своих собственных проектах (GBA/DS).

  • режим 'ползунка' Использования, поскольку это значительно уменьшает размер кода. На вариантах шины на 16 битов ARM (таких как GBA) существует также преимущество скорости.

  • 64k является серьезно маленьким для разработки C++. Я использовал бы C & Ассемблер в той среде.

На такой небольшой платформе необходимо будет остерегаться использования стека. Избегайте рекурсии, большие автоматические (локальные) структуры данных и т.д. Использование "кучи" также будет проблемой (новый, malloc и т.д.). C даст Вам больше контроля этих проблем.

1
ответ дан 28 November 2019 в 18:22
поделиться

функции времени обычно зависимы от операционной системы (если Вы не переписываете их). Используйте свои собственные функции (особенно, если у Вас есть RTC)

, шаблоны в порядке для использования, пока у Вас есть достаточно пространства для кода - othwerise, не используют их

, исключения не являются очень портативными также

функции printf, которые не делают , запись к буферу не является портативной (Вы должны быть так или иначе подключены к файловой системе для записи в ФАЙЛ* с printf). Используйте только sprintf, snprintf и str* функции (strcat, strlen) и конечно их широкие символьные корреспонденты (wcslen...).

, Если скорость является проблемой, возможно, необходимо использовать собственные контейнеры, а не STL (например, станд.:: отобразите контейнер, чтобы удостовериться, что ключ равен, делает 2 (да 2) сравнения с 'меньше' оператор ([меньше, чем] b == ложь & & b [меньше, чем] == ложь означают == b). 'меньше' - единственный параметр сравнения, полученный станд.:: класс сопоставления (и не только). Это может привести к некоторой потере производительности в критических стандартных программах.

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

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

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

иногда необходимо использовать режим Thumb а не Arm. Это может улучшить производительность.

Так для 64k памяти я сказал бы, что C++ с некоторыми его хорошими функциями (STL, исключения и т.д.) может быть излишеством. Я определенно выбрал бы C.

1
ответ дан 28 November 2019 в 18:22
поделиться

Относительно чрезмерного увеличения размера кода я думаю, что преступник, намного более вероятно, будет встроен , чем шаблоны.

, Например:

// foo.h
template <typename T> void foo () { /* some relatively large definition */ }

// b1.cc
#include "foo.h"
void b1 () { foo<int> (); }

// b2.cc
#include "foo.h"
void b2 () { foo<int> (); }

// b3.cc
#include "foo.h"
void b3 () { foo<int> (); }

компоновщик, скорее всего, объединит все определения 'нечто' в единственную единицу перевода. Поэтому размер 'нечто' не отличается от той из любой другой функции пространства имен.

, Если Ваш компоновщик не делает этого, то можно использовать явное инстанцирование, чтобы сделать это для Вас:

// foo.h
template <typename T> void foo ();

// foo.cc
#include "foo.h"
template <typename T> void foo () { /* some relatively large definition */ }
template void foo<int> ();        // Definition of 'foo<int>' only in this TU

// b1.cc
#include "foo.h"
void b1 () { foo<int> (); }

// b2.cc
#include "foo.h"
void b2 () { foo<int> (); }

// b3.cc
#include "foo.h"
void b3 () { foo<int> (); }

Теперь рассматривают следующее:

// foo.h
inline void foo () { /* some relatively large definition */ }

// b1.cc
#include "foo.h"
void b1 () { foo (); }

// b2.cc
#include "foo.h"
void b2 () { foo (); }

// b3.cc
#include "foo.h"
void b3 () { foo (); }

, Если компилятор решает встроить 'нечто' для Вас тогда, Вы закончите с 3 различными копиями 'нечто'. Никакие шаблоны в поле зрения!

РЕДАКТИРОВАНИЕ: Из комментария выше от InSciTek Jeff

Используя явные инстанцирования для функций, которые Вы знаете, будет использоваться только, можно также удостовериться, что все неиспользованные функции удалены (который может на самом деле уменьшить размер кода по сравнению с не, обрабатывают случай по шаблону):

// a.h
template <typename T>
class A
{
public:
  void f1(); // will be called 
  void f2(); // will be called 
  void f3(); // is never called
}


// a.cc
#include "a.h"

template <typename T>
void A<T>::f1 () { /* ... */ }

template <typename T>
void A<T>::f2 () { /* ... */ }

template <typename T>
void A<T>::f3 () { /* ... */ }

template void A<int>::f1 ();
template void A<int>::f2 ();

, Если Ваш набор инструментальных средств полностью не повреждается, вышеупомянутое генерирует код только для 'f1' и 'f2'.

1
ответ дан 28 November 2019 в 18:22
поделиться

В большинстве систем вы не хотите использовать new / delete , если вы не переопределили их своей собственной реализацией, которая извлекает из вашей собственной управляемой кучи. Да, это будет работать, но вы имеете дело с системой с ограниченным объемом памяти.

2
ответ дан 28 November 2019 в 18:22
поделиться

Если Вы используете ARM7TDMI, избегают невыровненные доступы памяти любой ценой .

основное ядро ARM7TDMI не имеет проверки выравнивания и возвратит повернутые данные, когда Вы делаете невыровненное чтение. Некоторые реализации имеют дополнительную схему для повышения ABORT исключение, но если у Вас нет одной из тех реализаций, находя, что ошибки из-за невыровненных доступов являются очень болезненными.

Пример:

const char x[] = "ARM7TDMI";
unsigned int y = *reinterpret_cast<const unsigned int*>(&x[3]);
printf("%c%c%c%c\n", y, y>>8, y>>16, y>>24);
  • На x86/x64 ЦП, это печатает "7TDM".
  • На ЦП SPARC, это выводит ядро с ошибкой шины.
  • На ЦП ARM7TDMI, это могло бы распечатать что-то как "7ARM" или "ITDM", предположив, что переменная "x" выровненная на 32-разрядной границе (который зависит от того, где "x" расположен и какие параметры компилятора используются, и т.д.), и Вы используете режим с прямым порядком байтов. Это - неопределенное поведение, но это в значительной степени гарантировало, что не работало способ, которым Вы хотите.
3
ответ дан 28 November 2019 в 18:22
поделиться

При использовании ARM7 и предположении, что у вас нет внешнего MMU, проблемы с динамическим распределением памяти могут быть сложнее отлаживать. Я бы добавил «разумное использование new / delete / free / malloc» в список руководств.

3
ответ дан 28 November 2019 в 18:22
поделиться

Это - интересное чтение для Объяснение на раннем , Встроенный C++ standrard

Видит этот статья о EC ++ также.

Встроенный станд. C++ был собственным подмножеством C++, т.е. это не имеет никаких дополнений. Следующие функции языка были удалены:

  • Множественное наследование
  • Виртуальные базовые классы
  • Информация о типах во время выполнения (идентификатор типа)
  • Модернизированные броски (static_cast, dynamic_cast, reinterpret_cast и const_cast)
  • изменяемый спецификатор типа
  • Пространства имен
  • Исключения
  • Шаблоны

Это отмечено на страница Wiki, которую говорит Bjarne Stroustrup (EC ++ станд.), "Насколько я знаю EC ++ мертво (2004), и если это не он, должен быть". Stroustrup продолжает рекомендовать документ , на который ссылается ответ Prakash.

4
ответ дан 28 November 2019 в 18:22
поделиться

Документ « Информационные технологии. Языки программирования, их среды и системные программные интерфейсы. Технический отчет о производительности C ++ » также содержит полезную информацию о программировании на C ++ для встроенного устройства.

5
ответ дан 28 November 2019 в 18:22
поделиться

Исключения, вероятно, будут наиболее распространенным ответом того, что избежать. Большинству реализаций стоили довольно большого статического ЗУ или стоимости памяти во время выполнения. Они также имеют тенденцию делать гарантии в реальном времени тяжелее.

Взгляд здесь для довольно хорошего примера стандарта кодирования, записанного для встроенного C++.

10
ответ дан 28 November 2019 в 18:22
поделиться

Выбор, чтобы избежать определенных функций, должен всегда основываться на количественном анализе поведения вашего программного обеспечения, на вашем оборудовании, с выбранным выбранным набором инструментов, в ограничения вашего домена влекут за собой. Существует много общепринятых «нехорошо» в разработке C ++, основанных на суевериях и древней истории, а не на твердых данных. К сожалению, это часто приводит к написанию большого количества дополнительного обходного кода, чтобы избежать использования функций, с которыми у кого-то когда-то были проблемы.

13
ответ дан 28 November 2019 в 18:22
поделиться

Я не сказал бы, что существует жесткое правило к этому; это во многом зависит от Вашего приложения. Встроенные системы обычно:

  • Более ограниченный в сумме памяти они имеют доступный
  • , Часто работает на более медленных аппаратных средствах
  • , Имеют тенденцию быть ближе к аппаратным средствам т.е. управлению им в некотором роде как игра с настройками регистра.

Точно так же, как любая другая разработка, хотя, необходимо сбалансировать все точки, Вы упомянули против требований, Вам дали / полученным.

1
ответ дан 28 November 2019 в 18:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: