В настоящее время наша команда использует некоторый перенесенный код из старой архитектуры в новый продукт на платформе ARM Cortex M3 с использованием настроенной версии GCC 4.5.1.Мы читаем данные из канала связи и пытаемся преобразовать необработанный байтовый массив в структуру для точного анализа данных.После наведения указателя на структуру и разыменования мы получаем предупреждение: «разыменование указателя типа, нарушенного правилами, будет нарушать правила строгого наложения имен».
После некоторых исследований я понял, что, поскольку массив char имеетнет правил выравнивания, и структура должна быть выровнена по словам, приведение указателей приводит к неопределенному поведению (плохая вещь).Мне интересно, есть ли лучший способ сделать то, что мы пытаемся.
Я знаю, что мы можем явно выровнять слова в массиве символов с помощью атрибута GCC ((выровненный (4)))».Я полагаю, что это сделает наш код "более безопасным", но предупреждения все еще будут загромождать наши сборки, и я не хочу отключать предупреждения в случае повторного возникновения этой ситуации.То, что мы хотим, - это способ безопасно делать то, что мы пытаемся, который будет информировать нас, если мы попытаемся сделать что-то небезопасное в другом месте позже.Поскольку это встроенная система, использование ОЗУ и флэш-памяти в некоторой степени важно.
Переносимость (компилятор и архитектура) не представляет большой проблемы, это касается только одного продукта.Однако, если существует переносимое решение, оно было бы предпочтительным.
Вот (очень упрощенный) пример того, что мы в настоящее время делаем:
#define MESSAGE_TYPE_A 0
#define MESSAGE_TYPE_B 1
typedef struct MessageA __attribute__((__packed__))
{
unsigned char messageType;
unsigned short data1;
unsigned int data2;
}
typedef struct MessageB __attribute__((__packed__))
{
unsigned char messageType;
unsigned char data3;
unsigned char data4;
}
// This gets filled by the comm system, assume from a UART interrupt or similar
unsigned char data[100];
// Assume this gets called once we receive a full message
void ProcessMessage()
{
MessageA* messageA;
unsigned char messageType = data[0];
if (messageType == MESSAGE_TYPE_A)
{
// Cast data to struct and attempt to read
messageA = (MessageA*)data; // Not safe since data may not be word aligned
// This may cause undefined behavior
if (messageA->data1 == 4) // warning would be here, when we use the data at the pointer
{
// Perform some action...
}
}
// ...
// process different types of messages
}