170 похожих чатов

#Вопрос к знатокам стандарта. Тут есть нарушение strict aliasing? uint8_t buffer[8]

= {1, 1, 1, 1, 0, 0, 0, 0};

uint32_t *p = reinterpret_cast<uint32_t *>(buffer);
printf("0x%x\n", *p);

32 ответов

19 просмотров

Зависит от того какой настоящий тип у uint8_t. Если один из стандартной тройки char, unsigned char, byte, вроде все ок.

Да, здесь прямое нарушение, как минимум дважды

magras
Но не правил алиасинга.

Нет, и правил алиасинга, именно что можно алиасить чаром всё что угодно, но не в обратную сторону. Здесь можно было бы поправить через использование memcpy, однако мы должны были бы копировать часть буфера, по размеру равную uint32_t

Liber Azerate
Нет, и правил алиасинга, именно что можно алиасить...

Возможно я ошибаюсь, но буфер char'ов всегда можно было использовать под любой тип. Да, объект в этом буфере нужно в начале создать и в примере выше есть проблемы с лайфтамом. Но мне сложно поверить что там есть проблема с алиасингом.

Liber Azerate
Нет, и правил алиасинга, именно что можно алиасить...

тривиальные типы и структуры вроде можно рентерпреткастить в/из char. Но не помню наверняка

Liber Azerate
Нет, и правил алиасинга, именно что можно алиасить...

Вопрос можно поставить даже проще: как реализовать std::vector если нельзя скастить массив char в массив T?

magras
Вопрос можно поставить даже проще: как реализовать...

Скастить-то можно, но не так https://eel.is/c++draft/basic.lval#11

Liber Azerate
Скастить-то можно, но не так https://eel.is/c++dra...

Так это проблема с лайфтамом, а не алиасингом.

magras
Так это проблема с лайфтамом, а не алиасингом.

Нет, здесь попытка прочитать значение через несоответствующий тип, нарушение strict aliasing. Чётко по пункту стандарта

Liber Azerate
Нет, здесь попытка прочитать значение через несоот...

Окей, я сформулирую свою мысль по-другому. В этом примере нет UB: char* buf = new char[sizeof(T)]; // assuming here that T has no overalignment new(buf) T; T* p = reinterpret_cast<T*>(buf); // я специально разделил placement new и каст *p; // read or write T

Liber Azerate
В первой части, до каста, нет

Почему после каста UB появляется? После placement new по адресу buf уже есть объект с типом T.

magras
Окей, я сформулирую свою мысль по-другому. В этом ...

Хотя я не прав и адрес возвращенный placement new может отличаться от reinterpret'а из-за особенностей new. Но это опять же не проблема алиасинга. upd: Это касается только создания массивов. Так как placement new у меня создает объект, а не массив, здесь проблемы не должно быть.

magras
Окей, я сформулирую свою мысль по-другому. В этом ...

Здесь нет UB, потому что есть динамический тип и с указателем на него ты работаешь, в исходном примере динамического типа нет.

Alexander Tulikov
Здесь нет UB, потому что есть динамический тип и с...

Да, но изначальный вопрос был только о алиасинге, а не UB в целом.

magras
Да, но изначальный вопрос был только о алиасинге, ...

Нет UB из-за strict aliasing violation потому, что динамические типы совпадают* А там есть

Liber Azerate
Нет UB из-за strict aliasing violation потому, что...

Ладно, предлагаю постановить что там есть UB по многим причинам: 1. aliasing 2. lifetime 3. alignment (возможно я еще что-то забыл) Я бы сказал, что нарушение lifetime было первично и если исправить его (как в моем примере) проблемы с алиасингом не будет. Но видимо это зависит от точки зрения.

magras
Ладно, предлагаю постановить что там есть UB по мн...

Согласен. Впрочем, используя type punning мы могли бы обойти нарушение strict aliasing и без решения каких-либо проблем с lifetime. Точнее, у нас бы их попросту не было

Liber Azerate
Согласен. Впрочем, используя type punning мы могли...

Это ведь про нововведение 20го стандарта? Там был список функций, которые такое делают: malloc, memcpy и прочие, но я не уверен, что оно неявно создает типы в обычных массивах на стеке. Пойду поищу пропозал.

magras
Это ведь про нововведение 20го стандарта? Там был ...

Вообще, в C++20 добавился bit_cast, насчёт memcpy, как мне кажется, это было и до 20-го стандарта

magras
Это ведь про нововведение 20го стандарта? Там был ...

> We propose that at minimum the following operations be specified as implicitly creating objects: > * Creation of an array of char, unsigned char, or std::byte implicitly creates objects within that array. Таки должно работать с обычными массивами. Если что это из [P0593R6].

magras
> We propose that at minimum the following operati...

P0593R0: What to do with buffers that are not arrays, and undefined behavior thereof? (by Ville Voutilainen) (2017-02-05) (Related: GitHub issue) P0593R1: Implicit creation of objects for low-level object manipulation (by Richard Smith, Ville Voutilainen) (2017-10-16) (Related: GitHub issue) P0593R2: Implicit creation of objects for low-level object manipulation (by Richard Smith) (2018-02-11) (Related: GitHub issue) P0593R3: Implicit creation of objects for low-level object manipulation (by Richard Smith) (2019-01-18) (Related: GitHub issue) P0593R4: Implicit creation of objects for low-level object manipulation (by Richard Smith) (2019-06-17) (Related: GitHub issue) P0593R5: Implicit creation of objects for low-level object manipulation (by Richard Smith) (2019-10-07) (Related: GitHub issue) P0593R6: Implicit creation of objects for low-level object manipulation (by Richard Smith, Ville Voutilainen) (2020-02-14) (Related: GitHub issue)

Liber Azerate
Вообще, в C++20 добавился bit_cast, насчёт memcpy,...

Не думаю. С memcpy трюк заключался в том, чтобы скопировать данные в уже существующий объект нужного типа. По-моему на cppref в статье про bit_cast была реализация для старых стандартов использующая этот прием.

magras
Не думаю. С memcpy трюк заключался в том, чтобы ск...

Ну да, объект должен был уже существовать. Вероятно, в том примере в любом случае необходимо было решить проблему с lifetime, так или иначе

magras
Окей, я сформулирую свою мысль по-другому. В этом ...

кстати можно же делать void* ptr = operator new(16, std::align_val_t(16));

Андрей Руссков
кстати можно же делать void* ptr = operator new(16...

Мне лень было искать точный синтаксис, чтобы задать правильное выравнивание, поэтому я использовал то что new char[] имеет максимальное "обычное" выравнивание и добавил комментарий про overalignment. =)

magras
Мне лень было искать точный синтаксис, чтобы задат...

разве через new если ааллцировать то у чар будет макс выравнивание? Я думал только через malloc

magras
> We propose that at minimum the following operati...

в стандарте оно вот здесь

Похожие вопросы

Обсуждают сегодня

Господа, а что сейчас вообще с рынком труда на делфи происходит? Какова ситуация?
Rꙮman Yankꙮvsky
29
А вообще, что может смущать в самой Julia - бы сказал, что нет единого стандартного подхода по многим моментам, поэтому многое выглядит как "хаки" и произвол. Короче говоря, с...
Viktor G.
2
30500 за редактор? )
Владимир
47
а через ESC-код ?
Alexey Kulakov
29
Гайс, вопрос для разносторонее развитых: читаю стрим с юарта, нада выделять с него фреймы с определенной структурой, если ли чо готовое, или долбаться с ринг буффером? нада у...
Vitaly
9
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
14
Добрый день! Скажите пожалуйста, а какие программы вы бы рекомендовали написать для того, чтобы научиться управлять памятью? Можно написать динамический массив, можно связный ...
Филипп
7
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
длина пакета фиксированная, или меняется?
Okhsunrog
7
Карта сайта