Я узнал, что, поскольку я использую формы Gatsbyjs и Gatsby + Netlify = javascript, мне нужно было добавить еще одну input type="hidden"
в мою форму:
Документация для этого была не сразу Ясно, но ниже приведены некоторые ссылки, которые обращаются к этому:
RTTI и Обработка исключений:
Шаблоны:
Виртуальные функции и наследование:
Обратите внимание, что стоимость исключений зависит от вашего кода. В одном профилированном приложении (относительно небольшое на ARM968) поддержка исключений добавила 2% к времени выполнения, а размер кода был увеличен на 9,5 КБ. В этом приложении исключения создавались только в том случае, если произошло что-то серьезно плохое, то есть никогда не происходило на практике, из-за чего время выполнения было очень низким
.Одна конкретная проблема, которая удивила меня ATMega GCC 3.something: когда я добавил виртуальную функцию тлеющих углей к одному из моих классов, я должен был добавить виртуальный деструктор. В той точке компоновщик попросил оператор удалять (пусто *). Я понятия не имею, почему это происходит, и добавление пустого определения для того оператора slolved проблема.
Убедитесь, что вы знаете, какие функции поддерживаются компилятором для вашей встроенной платформы, а также убедитесь, что вы знаете особенности вашей платформы. Например, компилятор CodeComposer от TI не выполняет автоматическое создание шаблонов. В результате, если вы хотите использовать сортировку STL, вам нужно вручную создать пять разных вещей. Он также не поддерживает потоки.
Другим примером является то, что вы можете использовать чип DSP, который не имеет аппаратной поддержки для операций с плавающей запятой. Это означает, что каждый раз, когда вы используете float или double, вы оплачиваете стоимость вызова функции.
Подводя итог, узнайте все, что нужно знать о вашей встроенной платформе и вашем компиляторе, и тогда вы будете знать, каких функций следует избегать.
Для встроенных систем Вы преимущественно захотите избежать вещей, которые имеют определенную аварийную стоимость во время выполнения. Некоторые примеры: исключения, и RTTI (для включения dynamic_cast и идентификатор типа ).
Если вы используете среду разработки, нацеленную на встраиваемую разработку, или определенную встроенную систему, она должна была уже ограничить некоторые варианты для вас. В зависимости от возможностей ресурса вашей цели, он отключит некоторые из вышеупомянутых элементов (RTTI, исключения и т. Д.). Это более простой путь, вместо того, чтобы помнить о том, что приведет к увеличению размера или требований к памяти (хотя, в любом случае, вы должны узнать это мысленно).
Используя и компилятор ARM GCC и собственный SDT ARM у меня были бы следующие комментарии:
ARM SDT производит более трудный, более быстрый код, но очень дорог (> Eur5k на рабочее место!). В моем предыдущем задании мы использовали этот компилятор, и это было в порядке.
инструменты GCC ARM работают очень хорошо, хотя и это - то, что я использую на своих собственных проектах (GBA/DS).
режим 'ползунка' Использования, поскольку это значительно уменьшает размер кода. На вариантах шины на 16 битов ARM (таких как GBA) существует также преимущество скорости.
64k является серьезно маленьким для разработки C++. Я использовал бы C & Ассемблер в той среде.
На такой небольшой платформе необходимо будет остерегаться использования стека. Избегайте рекурсии, большие автоматические (локальные) структуры данных и т.д. Использование "кучи" также будет проблемой (новый, malloc и т.д.). C даст Вам больше контроля этих проблем.
функции времени обычно зависимы от операционной системы (если Вы не переписываете их). Используйте свои собственные функции (особенно, если у Вас есть RTC)
, шаблоны в порядке для использования, пока у Вас есть достаточно пространства для кода - othwerise, не используют их
, исключения не являются очень портативными также
функции printf, которые не делают , запись к буферу не является портативной (Вы должны быть так или иначе подключены к файловой системе для записи в ФАЙЛ* с printf). Используйте только sprintf, snprintf и str* функции (strcat, strlen) и конечно их широкие символьные корреспонденты (wcslen...).
, Если скорость является проблемой, возможно, необходимо использовать собственные контейнеры, а не STL (например, станд.:: отобразите контейнер, чтобы удостовериться, что ключ равен, делает 2 (да 2) сравнения с 'меньше' оператор ([меньше, чем] b == ложь & & b [меньше, чем] == ложь означают == b). 'меньше' - единственный параметр сравнения, полученный станд.:: класс сопоставления (и не только). Это может привести к некоторой потере производительности в критических стандартных программах.
шаблоны, исключения увеличивают размер кода (можно быть уверены в этом). иногда даже производительность затронута при наличии большего кода.
функции выделения памяти, вероятно, должны быть переписаны также, потому что они зависимы от операционной системы во многих отношениях (особенно при контакте с выделением памяти потокобезопасности).
malloc использует _end переменную (объявляемый обычно в сценарии компоновщика) для выделения памяти, но это не ориентировано на многопотоковое исполнение в "неизвестных" средах.
иногда необходимо использовать режим Thumb а не Arm. Это может улучшить производительность.
Так для 64k памяти я сказал бы, что C++ с некоторыми его хорошими функциями (STL, исключения и т.д.) может быть излишеством. Я определенно выбрал бы C.
Относительно чрезмерного увеличения размера кода я думаю, что преступник, намного более вероятно, будет встроен , чем шаблоны.
, Например:
// 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'.
В большинстве систем вы не хотите использовать new / delete , если вы не переопределили их своей собственной реализацией, которая извлекает из вашей собственной управляемой кучи. Да, это будет работать, но вы имеете дело с системой с ограниченным объемом памяти.
Если Вы используете 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);
При использовании ARM7 и предположении, что у вас нет внешнего MMU, проблемы с динамическим распределением памяти могут быть сложнее отлаживать. Я бы добавил «разумное использование new / delete / free / malloc» в список руководств.
Это - интересное чтение для Объяснение на раннем , Встроенный C++ standrard
Видит этот статья о EC ++ также.
Встроенный станд. C++ был собственным подмножеством C++, т.е. это не имеет никаких дополнений. Следующие функции языка были удалены:
Это отмечено на страница Wiki, которую говорит Bjarne Stroustrup (EC ++ станд.), "Насколько я знаю EC ++ мертво (2004), и если это не он, должен быть". Stroustrup продолжает рекомендовать документ , на который ссылается ответ Prakash.
Документ « Информационные технологии. Языки программирования, их среды и системные программные интерфейсы. Технический отчет о производительности C ++ » также содержит полезную информацию о программировании на C ++ для встроенного устройства.
Исключения, вероятно, будут наиболее распространенным ответом того, что избежать. Большинству реализаций стоили довольно большого статического ЗУ или стоимости памяти во время выполнения. Они также имеют тенденцию делать гарантии в реальном времени тяжелее.
Взгляд здесь для довольно хорошего примера стандарта кодирования, записанного для встроенного C++.
Выбор, чтобы избежать определенных функций, должен всегда основываться на количественном анализе поведения вашего программного обеспечения, на вашем оборудовании, с выбранным выбранным набором инструментов, в ограничения вашего домена влекут за собой. Существует много общепринятых «нехорошо» в разработке C ++, основанных на суевериях и древней истории, а не на твердых данных. К сожалению, это часто приводит к написанию большого количества дополнительного обходного кода, чтобы избежать использования функций, с которыми у кого-то когда-то были проблемы.
Я не сказал бы, что существует жесткое правило к этому; это во многом зависит от Вашего приложения. Встроенные системы обычно:
Точно так же, как любая другая разработка, хотя, необходимо сбалансировать все точки, Вы упомянули против требований, Вам дали / полученным.