Как обрабатываются переменные, объявленные в функции после ее завершения - PullRequest
0 голосов
/ 14 июня 2019

Мне интересно, как поведение памяти / переменных в следующем коде.По сути, я добавляю epd_tx_buffer в массив в epd_driver_state с помощью epd_power_on ().

Затем эти буферы используются / асинхронно используются через механизм, управляемый событиями.Мое беспокойство / что я хочу знать, будет ли содержимое области памяти, указанной "uint8_t * buffer", постоянным или возможно, что оно может быть перезаписано.По завершении epd_power_on будет выполняться другой код до тех пор, пока асинхронное событие не займет буфер.

struct epd_tx_buffer {
    uint8_t hasCmd;
    uint8_t * buffer;
    uint16_t bufferLen;
    uint8_t wait_ms;
};

static struct epd_driver_state {
    uint8_t cursor;
    uint8_t length;
    struct epd_tx_buffer buff[256];
    bool isRunning;
} epd_driver_state;

static void epd_power_on(void){
    addToSPIQueueCommandData( ( uint8_t[] ) { POWER_ON }, 1 );
    addToSPIQueueCommandData( ( uint8_t[] ) { PANEL_SETTING, 0x2F }, 2 );
    addToSPIQueueCommandData( ( uint8_t[] ) { PLL_CONTROL, 0x3A }, 2 );
    addToSPIQueueCommandData( ( uint8_t[] ) { POWER_SETTING, 0x03, 0x00, 0x2B, 0x2B, 0x09 }, 6 );
    addToSPIQueueCommandData( ( uint8_t[] ) { BOOSTER_SOFT_START, 0x07, 0x07, 0x17  }, 4);
    addToSPIQueueCommandData( ( uint8_t[] ) { VCM_DC_SETTING_REGISTER, 0x00 }, 2 );
    addToSPIQueueCommandData( ( uint8_t[] ) { VCOM_AND_DATA_INTERVAL_SETTING, 0x47 }, 2 );
}



bool addToSPIQueueCommandData(uint8_t * buffer, uint16_t bufferLen)
{
    if( epd_driver_state.length >= 255 ) return false;
    epd_driver_state.buff[ epd_driver_state.length ].hasCmd         = 1;
    epd_driver_state.buff[ epd_driver_state.length ].buffer         = buffer;
    epd_driver_state.buff[ epd_driver_state.length ].bufferLen      = bufferLen;
    epd_driver_state.length++;
    return true;
}

Некоторые объяснения будут высоко оценены!

Ответы [ 2 ]

0 голосов
/ 14 июня 2019

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

Проще говоря, приведенный код представляет собой одно огромное неопределенное поведение

Вы должны убедиться, что время жизни объекта настолько велико, насколько это необходимо. В этом случае это не

0 голосов
/ 14 июня 2019
addToSPIQueueCommandData( ( uint8_t[] ) { POWER_ON }, 1 );
addToSPIQueueCommandData( ( uint8_t[] ) { PANEL_SETTING, 0x2F }, 2 );
addToSPIQueueCommandData( ( uint8_t[] ) { PLL_CONTROL, 0x3A }, 2 );
addToSPIQueueCommandData( ( uint8_t[] ) { POWER_SETTING, 0x03, 0x00, 0x2B, 0x2B, 0x09 }, 6 );
addToSPIQueueCommandData( ( uint8_t[] ) { BOOSTER_SOFT_START, 0x07, 0x07, 0x17  }, 4);
addToSPIQueueCommandData( ( uint8_t[] ) { VCM_DC_SETTING_REGISTER, 0x00 }, 2 );
addToSPIQueueCommandData( ( uint8_t[] ) { VCOM_AND_DATA_INTERVAL_SETTING, 0x47 }, 2 );

Это составные литералы массива, они выйдут из области видимости после выхода из функции. Таким образом, доступ к ним вне функции с использованием ссылки неопределенное поведение .


Вы могли бы рассмотреть это, как показано ниже.

uint8_t *temp = malloc(sizeof((( uint8_t[] ) { PLL_CONTROL, 0x3A })));
memcpy(temp, (( uint8_t[] ) { PLL_CONTROL, 0x3A }), 2);
addToSPIQueueCommandData(temp, 2);

Примечание: убедитесь, что free память когда-то закончила обработку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...