Как безопасно выполнять набор текста во встроенной системе

Наша команда в настоящее время использует некоторый перенесенный код из старой архитектуры в новый продукт, основанный на платформе 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
}
6
задан shenles 25 January 2012 в 23:18
поделиться