Название: Тупой вопрос про выравнивание Отправлено: Авварон от Май 27, 2019, 19:12 Вот есть такой код:
Код: #define AES_N_BLOCK 16 Юзается так: Код: void aes_decrypt(const quint8 in[AES_N_BLOCK], quint8 out[AES_N_BLOCK]) { Анализатор кланга ругается что одна из ячеек s1 не иницилизирована. Если я убираю reinterpret_cast из quint8 в quint64 и xor'ю в цикле, то ругаться перестает. Это бага анализатора? Или это связано с выравниванием - что никто не гарантирует выравнивание quint8 s1[16] на 8 байт? Или гарантируют? На x86_64 добиться левого выравнивания на стеке\маллоком не удалось... В код можно потупить тут (http://libbtc.github.io/libbtc/html/aes_8c_source.html), у нас копия, но почти 1в1, судя по всему. Функции aes_cbc_decrypt, aes_decrypt, copy_and_key Название: Re: Тупой вопрос про выравнивание Отправлено: Igors от Май 28, 2019, 11:43 Объявите union'ом, для удобства присваивания quint64 первым
Название: Re: Тупой вопрос про выравнивание Отправлено: Авварон от Май 28, 2019, 11:52 Объявите union'ом, для удобства присваивания quint64 первым Это такое же UB как и код выше. Нельзя использовать union для type prunning'а. Единственный способ делать type prunning - это memcopy, и да, это тоже помогает "заткнуть" анализатор. Но всё же хочется воспроизвести проблему, я что не пытаюсь сделать - адреса выровнены, хоть убей. Или это очередная "фишка" х86? Название: Re: Тупой вопрос про выравнивание Отправлено: Igors от Май 28, 2019, 12:46 Если нужен только xor то его проще реализовать не привлекая quint64. Насколько понял, Вас волнует что при "наложении" этой структуры на какую-то область памяти адрес quint64 окажется не кратным 8. Не вижу почему это не должно работать. Напр
Код Так делать не запрещено, нечетный адрес val замедлит выполнение, но и только Ну или рисовать геттеры/сеттеры c memmоve внутри (чтоб сердце успокоилось) Название: Re: Тупой вопрос про выравнивание Отправлено: Авварон от Май 28, 2019, 16:12 Так делать не запрещено, нечетный адрес val замедлит выполнение, но и только Я в этом не уверен :)Цитировать Taking the address of a field in a #pragma packed struct does not yield a __packed pointer, so the compiler will not produce an error if you assign this address to a non-__packed pointer. However, the field might not be properly aligned for its type, and dereferencing such an unaligned pointer results in Undefined behavior. отсюда (http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491g/CJAFEEDG.html) Но мы отвлеклись, вопрос не в том, можно ли reinterpret_cast'ить невровненные адреса. Понятно, что нельзя. Вопрос-то про конкретный код, где мы передаем в функцию uint8[16], созданный на стеке. Он будет выровнен или нет? Мои знания говорят, что нет, но мои эксперименты на x86 этого не подтверждают - у меня не получилось создать невыровненный массив на стеке. Название: Re: Тупой вопрос про выравнивание Отправлено: ViTech от Май 28, 2019, 17:42 Вопрос-то про конкретный код, где мы передаем в функцию uint8[16], созданный на стеке. Он будет выровнен или нет? Мои знания говорят, что нет, но мои эксперименты на x86 этого не подтверждают - у меня не получилось создать невыровненный массив на стеке. Про выравнивание мало что могу точно сказать, нужно букварь больше читать. Посмотрите, как располагаются в памяти массивы с другим размером, например uint8[15]. У меня в отладчике такой не выглядит выровненным. Может конкретно uint8[16] компилятор скорей всего выровняет (и выравнивает), но не обязан это делать, на что clang и обращает внимание. alignas (https://en.cppreference.com/w/cpp/language/alignas) в данной ситуации может помочь? Название: Re: Тупой вопрос про выравнивание Отправлено: Old от Май 28, 2019, 21:45 Это бага анализатора? Думается мне, что это именно анализатор тупит.Или это связано с выравниванием - что никто не гарантирует выравнивание quint8 s1[16] на 8 байт? А для чего здесь иметь обязательно выравненное значение? x86_64 может читать/писать не выравненные данные.На x86_64 добиться левого выравнивания на стеке\маллоком не удалось... Попробуйте так:quint8 s1[AES_N_BLOCK+1]; плюс этот массив можно инициализировать какими-то значениями и после отработки функции посмотреть все ли в нем изменилось. Update. А вот на некоторых армовских ядрах могут быть проблемы с этим. Возможно анализатор заточен на некий общий случай. Название: Re: Тупой вопрос про выравнивание Отправлено: _Bers от Июнь 01, 2019, 13:39 Это бага анализатора? код содержит UB. 1. нарушение стрикт-алиасинга. 2. нет гарантий для выравнивания. Название: Re: Тупой вопрос про выравнивание Отправлено: Авварон от Июнь 01, 2019, 16:26 Это бага анализатора? код содержит UB. 1. нарушение стрикт-алиасинга. 2. нет гарантий для выравнивания. 1. Верно я понимаю, что исключения для стрикт алиссинга распространяется только на void*,char*,uchar*,std::byte*? 2. Так поможет?: Код: struct alignas(alignof(uint64_t)) AesBlock { uchar8_t data[16]; } Если я буду передавать const-ref структуры и возвращать копию структуры будет ок? Название: Re: Тупой вопрос про выравнивание Отправлено: Igors от Июнь 02, 2019, 07:47 Гарантируют - не гарантируют... Хочется чтоб "никто не подкопался" - ну просто так
Код
Название: Re: Тупой вопрос про выравнивание Отправлено: Авварон от Июнь 02, 2019, 12:15 Ну способ с memcpy понятен, только зачем, можно просто побайтовом покорить - будет быстрее, скорее всего.
Так-то велосипед писать не надо, всё уже написано за вас (https://github.com/qt/qtbase/blob/5.12/src/corelib/global/qendian.h#L64). Название: Re: Тупой вопрос про выравнивание Отправлено: Igors от Июнь 02, 2019, 13:21 Ну способ с memcpy понятен, Если понятен - то надо делать и забывать :)всё уже написано за вас (https://github.com/qt/qtbase/blob/5.12/src/corelib/global/qendian.h#L64). Я давно заметил что "богатырская сила" охотно демонстрируется когда и без нее проблем нет. А вот когда трудности и помощь была бы очень кстати - не дождесся :'( |