Почему этот код дает сбой на HPUX?

Я написал небольшую программу, которая напоминает проблему, с которой я сталкиваюсь в своем проекте. Вопрос в том, почему происходит сбой при запуске на платформе HP-UX?

Ошибка :

si_code: 1 - BUS_ADRALN - Неверное выравнивание адреса

Код :

int main()
{
    uint8_t *cmd ;
    cmd = (uint8_t *) malloc(77);
    uint32_t gen = 20; 
    *(uint32_t*)&cmd[10] = gen;  /* crash here */
    return 0;
}

person Manoj Hirway    schedule 17.02.2015    source источник
comment
(uint32_t)&cmd[11] = gen; /* здесь происходит сбой */ --› Можете ли вы попробовать 11 вместо 10?   -  person simurg    schedule 17.02.2015
comment
Точно так же вылетает на 11.   -  person Manoj Hirway    schedule 17.02.2015
comment
@ManojHirway Как насчет 12?   -  person Arkku    schedule 17.02.2015
comment
Чтобы cmd[10] было выровнено по 32 битам, cmd должно быть выровнено по 16 битам, а не по 32 битам. Если это не так, И ваша платформа (т. е. базовая аппаратная архитектура + назначенный компилятор) не поддерживает невыровненные операции загрузки/сохранения, тогда эта операция приведет к неопределенному поведению. Если повезет, то он сразу вылетит и даст понять, что в этой строке что-то не так. Если вам не повезло, то он просто сохранит значение в другом смещении в пределах cmd, и программа будет вести себя неожиданно.   -  person barak manos    schedule 17.02.2015
comment
@barakmanos По спецификациям malloc, cmd никогда не будут «не выравнены на 32 бита» на платформе с типом данных, требующим такого выравнивания — память malloced выровнена для любого типа данных, поэтому в этом случае неправильное выравнивание в принципе гарантировано.   -  person Arkku    schedule 17.02.2015
comment
Кстати, это также нарушает строгие требования к псевдонимам, а не только требования к выравниванию. memcpy(&cmd[10], &gen, sizeof gen); должен решить обе проблемы.   -  person mafso    schedule 17.02.2015


Ответы (1)


&cmd[10] не выровнен должным образом для хранения 32-битного целого числа — поскольку каждый элемент cmd имеет длину в один байт, а адрес, возвращаемый malloc, правильно выровнен для «любого типа», 11-й элемент cmd не будет по адресу, кратному кратности на 4.

person Arkku    schedule 17.02.2015
comment
Спасибо. Но разве мы не имеем в виду 4 байта вместе, когда приводим его к типу (uint32_t *)&cmd[10]? - person Manoj Hirway; 17.02.2015
comment
@ManojHirway Выполняя приведение, вы обрабатываете данные как uint32_t, и компилятор генерирует код, который работает с этим типом, а не код, который работает с «любыми 4 байтами вместе»… Таким образом, требования выравнивания uint32_t вступают в игру. (Компилятор clang фактически выдает предупреждение об этой строке в вашем коде, если вы включили -Wcast-align.) - person Arkku; 17.02.2015