У меня есть объединение (ValueDefinition) с указателями различных типов данных и функций для его создания. С String все работает нормально:
ValueDefinition CreateValDefString(String value){
ValueDefinition valDef = {.ValueString = new String(value)};
return valDef;
}
Но когда я делаю то же самое с напр. uint8_t компилируется, но во время выполнения я получаю эту ошибку:
[E][WString.cpp:185] changeBuffer(): realloc failed! Buffer unchanged
Это код для uint8_t:
ValueDefinition CreateValDefUint8(uint8_t value){
ValueDefinition valDef = {.ValueUInt8 = new uint8_t(value)};
return valDef;
}
Что я делаю неправильно? Я пробовал это без «new» и с malloc, но я все еще получаю ту же ошибку.
Изменить: По запросу, определение ValueDefinition:
union ValueDefinition{
bool* ValueBool;
int8_t* ValueInt8;
int16_t* ValueInt16;
int32_t* ValueInt32;
uint8_t* ValueUInt8;
uint16_t* ValueUInt16;
uint32_t* ValueUInt32;
float* ValueFloat;
ulong* ValueULong;
String* ValueString;
};
В вашем коде похоже, что C ++ выдает ошибку функции, чтобы создать WString
вместо uint8_t
следовательно, трассировка стека в совершенно отдельном заголовке. Поиск исходного кода в хранилище для arduino показывает, что в WString.cpp есть ошибка Вот, это то, что обнаруживает ваш компилятор.
Пользователи github предлагают использовать другую библиотеку строк, и, поскольку ошибка не устранена, вам придется изменить ее, возможно, на стандартную. string
библиотека определяется C ++ и не Arduino. Как заявили пользователи на github, строки arduino общеизвестно ненадежны.
Другими словами, эта ошибка не имеет ничего общего с вашим кодом, но я хотел бы задать вопрос: «Зачем использовать объединения в C ++?» Если вы хотите определить универсальный тип, просто используйте угловые скобки в объявлении типа, например:
class ValueDefinition<T> {
private:
T typeDat;
public:
Valuedefinition<T>(T t);
/* etc. */
}
Объединения были созданы таким образом, чтобы C мог использовать универсальную типизацию, используя несколько типов для совместного использования данных в объединении. Другое распространенное использование — использование преимуществ типов данных, использующих одну и ту же память, чтобы найти базовый двоичный файл более сложных типов, например использование отдельных uint8_t
значения, лежащие в основе long long
чтобы найти значение его битов или используя int
чтобы получить двоичное значение float
Пример:
union foo {
uint8_t bits[4]; /* Represent the bits of 'data' */
long long int data;
}
union foo myLong = {.data = 12378591249169278l};
printf("%d\n", myLong.bits[0]); // Returns the value of the high bit of myLong
Однако обратите внимание, что это неопределенное поведение так как союзы обычно дополняются, так что не пытайтесь это делать ни в коем случае. Что бы вы ни делали, если вы используете C ++, есть лучшее решение, чем использование союзов, так как это была функция, предназначенная для языка, который не имел универсальной типизации чтобы сохранить память.
Редактировать:
Инициализируйте ValueDefinition следующим образом, используя управление памятью в стиле C:
union ValueDefinition *value = malloc(sizeof(union ValueDefinition));
value->ValueUInt8 = malloc(sizeof(uint8_t));
/* more code */
Или с C ++ new
:
union ValueDefinition *value = new ValueDefinition();
value->ValueUInt8 = new uint8_t(/* Some number */);
/* more code */
Других решений пока нет …