Size: a a a

2020 November 27

m

magras in pro.cxx
Liber Azerate
Нет, и правил алиасинга, именно что можно алиасить чаром всё что угодно, но не в обратную сторону. Здесь можно было бы поправить через использование memcpy, однако мы должны были бы копировать часть буфера, по размеру равную uint32_t
Вопрос можно поставить даже проще: как реализовать std::vector если нельзя скастить массив char в массив T?
источник

LA

Liber Azerate in pro.cxx
magras
Вопрос можно поставить даже проще: как реализовать std::vector если нельзя скастить массив char в массив T?
Скастить-то можно, но не так
https://eel.is/c++draft/basic.lval#11
источник

m

magras in pro.cxx
Liber Azerate
Скастить-то можно, но не так
https://eel.is/c++draft/basic.lval#11
Так это проблема с лайфтамом, а не алиасингом.
источник

LA

Liber Azerate in pro.cxx
magras
Так это проблема с лайфтамом, а не алиасингом.
Нет, здесь попытка прочитать значение через несоответствующий тип, нарушение strict aliasing. Чётко по пункту стандарта
источник

m

magras in pro.cxx
Liber Azerate
Нет, здесь попытка прочитать значение через несоответствующий тип, нарушение strict aliasing. Чётко по пункту стандарта
Окей, я сформулирую свою мысль по-другому. В этом примере нет 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
источник

LA

Liber Azerate in pro.cxx
magras
Окей, я сформулирую свою мысль по-другому. В этом примере нет 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
В первой части, до каста, нет
источник

m

magras in pro.cxx
Liber Azerate
В первой части, до каста, нет
Почему после каста UB появляется?
После placement new по адресу buf уже есть объект с типом T.
источник

m

magras in pro.cxx
magras
Окей, я сформулирую свою мысль по-другому. В этом примере нет 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
Хотя я не прав и адрес возвращенный placement new может отличаться от reinterpret'а из-за особенностей new. Но это опять же не проблема алиасинга.

upd: Это касается только создания массивов. Так как placement new у меня создает объект, а не массив, здесь проблемы не должно быть.
источник

AT

Alexander Tulikov in pro.cxx
magras
Окей, я сформулирую свою мысль по-другому. В этом примере нет 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
Здесь нет UB, потому что есть динамический тип и с указателем на него ты работаешь, в исходном примере динамического типа нет.
источник

LA

Liber Azerate in pro.cxx
Alexander Tulikov
Здесь нет UB, потому что есть динамический тип и с указателем на него ты работаешь, в исходном примере динамического типа нет.
Да, пожалуй здесь я ошибся
источник

m

magras in pro.cxx
Alexander Tulikov
Здесь нет UB, потому что есть динамический тип и с указателем на него ты работаешь, в исходном примере динамического типа нет.
Да, но изначальный вопрос был только о алиасинге, а не UB в целом.
источник

D

Danya in pro.cxx
А где можно найти определение "динамического типа"?
источник

LA

Liber Azerate in pro.cxx
magras
Да, но изначальный вопрос был только о алиасинге, а не UB в целом.
Нет UB из-за strict aliasing violation потому, что динамические типы совпадают*
А там есть
источник
2020 November 28

m

magras in pro.cxx
Liber Azerate
Нет UB из-за strict aliasing violation потому, что динамические типы совпадают*
А там есть
Ладно, предлагаю постановить что там есть UB по многим причинам:
1. aliasing
2. lifetime
3. alignment
(возможно я еще что-то забыл)

Я бы сказал, что нарушение lifetime было первично и если исправить его (как в моем примере) проблемы с алиасингом не будет. Но видимо это зависит от точки зрения.
источник

LA

Liber Azerate in pro.cxx
magras
Ладно, предлагаю постановить что там есть UB по многим причинам:
1. aliasing
2. lifetime
3. alignment
(возможно я еще что-то забыл)

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

AP

Alexander Pshenichni... in pro.cxx
Всем спасибо за ответы.
источник

m

magras in pro.cxx
Liber Azerate
Согласен. Впрочем, используя type punning мы могли бы обойти нарушение strict aliasing и без решения каких-либо проблем с lifetime. Точнее, у нас бы их попросту не было
Это ведь про нововведение 20го стандарта? Там был список функций, которые такое делают: malloc, memcpy и прочие, но я не уверен, что оно неявно создает типы в обычных массивах на стеке. Пойду поищу пропозал.
источник

LA

Liber Azerate in pro.cxx
Danya
А где можно найти определение "динамического типа"?
источник

LA

Liber Azerate in pro.cxx
magras
Это ведь про нововведение 20го стандарта? Там был список функций, которые такое делают: malloc, memcpy и прочие, но я не уверен, что оно неявно создает типы в обычных массивах на стеке. Пойду поищу пропозал.
Вообще, в C++20 добавился bit_cast, насчёт memcpy, как мне кажется, это было и до 20-го стандарта
источник

m

magras in pro.cxx
magras
Это ведь про нововведение 20го стандарта? Там был список функций, которые такое делают: malloc, memcpy и прочие, но я не уверен, что оно неявно создает типы в обычных массивах на стеке. Пойду поищу пропозал.
> 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].
источник