LINUX.ORG.RU
Ответ на: комментарий от anonymous

с такой, что memcpy прост как 3 копейки. это же простое копирование байт. выравнивание здесь по боку, оптимизатор тоже ничего не испортит. здесь просто нечему ломаться
http://dbp-consulting.com/tutorials/StrictAliasing.html

tyro33
() автор топика
Ответ на: комментарий от tyro33

http://dbp-consulting.com/tutorials/StrictAliasing.html

Недавно была темка в std-discussion про memcpy.
Пришли к выводу, что подобное использование memcpy в C++ это UB, с C — неясно. Прямо указаний на определённое поведение нет, есть какие-то полунамёки.

anonymous
()
Ответ на: комментарий от anonymous

ну вообще логично. memcpy внутри ведь тоже как-то кастует указатели, а значит там может всплыть то же самое нарушение strict aliacing. возиться с байтами в цепепе себе дороже. если и в сишке такая же порнография - это вообще атас. «кроссплатформенный ассемблер», где простейшая операция с байтами любыми способами сводится к UB, бгг

tyro33
() автор топика
Ответ на: комментарий от anonymous

А если обернуть в препроцессорную обмазку, это снимет UB? :D

Нет, компилятор видит код уже после препроцессора.

KennyMinigun ★★★★★
()
Ответ на: комментарий от tyro33

ну вообще логично. memcpy внутри ведь тоже как-то кастует указатели, а значит там может всплыть то же самое нарушение strict aliacing.

memcpy это библиотечная функция, на неё не распространяются никакие правила. Она работает так, как определено стандартом. Даже если ты посмотришь в её реализацию и увидишь там возможные нарушения.

anonymous
()
Ответ на: комментарий от anonymous

Она работает так, как определено стандартом

тогда каким образом товарищи пришли к выводу, что использование memcpy в C++ - это UB?

tyro33
() автор топика
Ответ на: комментарий от anonymous

я знаю. но если memcpy работает как положено стандартом, то почему оно не defined? стандарт сам себе не defined, что ли? это же абсурд

tyro33
() автор топика
Ответ на: комментарий от tyro33

но если memcpy работает как положено стандартом, то почему оно не defined?

Не defined использовать memcpy как в той статье, для копирования байтов из одного типа в другой.

anonymous
()
Ответ на: комментарий от anonymous

ну в цепепе охотно верится (хотя впервые слышу). а в сишке уверен, что нет. memcpy так юзают повсеместно. даже в примерах документации копируют int64_t в double и не чешутся

tyro33
() автор топика
Ответ на: комментарий от tyro33

memcpy так юзают повсеместно. даже в примерах документации копируют int64_t в double и не чешутся

Ну и? Iron_Bug и от кода в ОП-посте не чешется.

UB не значит, что «не соответствует ожиданиям.»

anonymous
()
Ответ на: комментарий от anonymous

Ну и? Iron_Bug и от кода в ОП-посте не чешется.

отличие очень простое:
1. код в посте, согласно документации - не валиден
2. код с memcpy, согласно документации - валиден
документация прямо разрешает юзать memcpy как раз в таких вот случаях, как в посте:

Where strict aliasing prohibits examining the same memory as values of two different types, memcpy may be used to convert the values.

поэтому нет видимых оснований считать код c memcpy UB (случаи UB для memcpy там тоже указаны и ничего про типы там нет) ну либо доку пишут диверсанты, которые хотят, чтобы разработчики отстреляли себе не только ноги, но и яйца, а сишка не пригодна для банальных байтовых операций от слова совсем
p/s. цитата касается си, как там с этим в цепепе не знаю

tyro33
() автор топика

такую наркоманию

Сам ты наркоман! Это — нормально! Единственный косяк — не забывать о «конечности», и если на тупоконечной машине это будет запускаться, возможно, не пройдет. Поэтому UB. Но элементарные операции преобразования помогут.

anonymous
()
Ответ на: комментарий от Deleted

Поскольку ваше утверждение первое, то начинать вам

Твои детсадовские методы тут не пройдут. UB — отсутствие определённого поведения. Отсутствие доказать невозможно, кроме как тем фактом, что определение поведения не предъявлено.

Так что расписывай поведение со ссылками на стандарт или оно автоматически не определено.

anonymous
()
Ответ на: комментарий от tyro33

1. код в посте, согласно документации - не валиден
2. код с memcpy, согласно документации - валиден

Какая документация во втором случае? Если в первом случае стандарт, то во втором — мнение частного лица.

нет видимых оснований считать код c memcpy UB

Видимых — это чтобы компилятор делал что-то неожиданное с кодом с UB в подобном коде? Да, таких случаев я не знаю. И не утверждал, что они есть. К тому же, я сказал, что насчёт C до конца не ясно, что там UB. Вроде есть полунамёки, что так можно, но они очень косвенные.

а сишка не пригодна для банальных байтовых операций от слова совсем

Ну как бы да. Даже читать из неактивного члена union-а в стандарте C разрешает подстрочное примечание. А как известно, подстрочные примечания не нормативны (не являются правилами). Если так понимать, то читать из неактивного члена union UB не только в C++, но и в C. Хотя бытует мнение, что в C это где-то разрешено.

anonymous
()
Ответ на: комментарий от anonymous

Это — нормально!
Поэтому UB.

сам-то понял, что написал?
намерения кода очевидны, вопрос был вообще про другое

tyro33
() автор топика
Ответ на: комментарий от anonymous

Какая документация во втором случае? Если в первом случае стандарт, то во втором — мнение частного лица.

http://en.cppreference.com/w/c/string/byte/memcpy Утверждение логично следует из куска стандарта, который привели выше. Видимо, уже не раз задавались этим вопросом, вот и вписали
Прямого разрешения в стандарте, конечно, не найти. Хотя бы потому что стандарт не может предусмотреть все возможные варианты использования и регламентировать каждый чих. Стандарт просто задает правила, а задача программиста стараться их не нарушать.

Вроде есть полунамёки, что так можно, но они очень косвенные

В одном случае прямое указание на нарушение, в другом косвенные полунамеки. Выбор очевиден, потому что операцию все равно надо как-то выполнять. Остается довериться здравому смыслу, либо вообще бросить си. Так как по такой логике UB можно заподозрить в чем угодно

tyro33
() автор топика
Ответ на: комментарий от tyro33

Утверждение логично следует из куска стандарта, который привели выше.

В C++ есть точно такой же кусок про aliasing. При этом не считается, что он разрешает делать memcpy между объектами разных типов. Более того, считается, что явное описание поведения memcpy между объектами одного и того же trivially copyable типа (http://eel.is/c draft/basic.types#2 и http://eel.is/c draft/basic.types#3) говорит о том, что в других случаях поведение не определено.

Местом, которое размыто намекает, что memcpy в C делать можно (т.е. есть какие-то способы изменения значения объекта кроме как через lvalue типа этого объекта) это:

6.2.6.1/5

Certain object representations need not represent a value of the object type. If the stored value of an object has such a representation and is read by an lvalue expression that does not have character type, the behavior is undefined. If such a representation is produced by a side effect that modifies all or any part of the object by an lvalue expression that does not have character type, the behavior is undefined. 50) Such a representation is called a trap representation.

стандарт не может предусмотреть все возможные варианты использования и регламентировать каждый чих

Да. Для этого ввели понятие неопределённого поведения:

3.4.3/1

behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements

4/2

If a ‘‘shall’’ or ‘‘shall not’’ requirement that appears outside of a constraint or runtime- constraint is violated, the behavior is undefined. Undefined behavior is otherwise indicated in this International Standard by the words ‘‘undefined behavior’’ or by the omission of any explicit definition of behavior. There is no difference in emphasis among these three; they all describe ‘‘behavior that is undefined’’.

И если стандарт не описал какой-то чих, сиди гадай, это UB или надо высасывать из какого-то пальца определение этого поведения. (Меня, например, 6.2.6.1/5 не особо убеждает что memcpy определён, я могу и другие интерпретации подобрать к этому параграфу).

anonymous
()
Ответ на: комментарий от tyro33

Если адрес выровнен и код будет только на узкоконечной архитектуре запускаться, то никакого UB не будет. Но если автор решит перенести это на тупоконечную, или же адрес вдруг будет не выровнен, начнутся приколы.

Так что, больше UB, нежели хорошо.

Я уже разгребал чужой код, писанный под 32-битную архитектуру с использованием всяких сволочных char'ов, int'ов и long'ов вместо нормальных int8_t и т.п. Дня три убил, пока оно у меня на 64-битной архитектуре взлетело. Сам тоже натыкался на косяк: использовал ассемблерные вставки для оптимизации кода, в итоге оно на ARM'ах компиляться отказывалось. Боюсь, если вдруг мне попадется тупоконечная машина, то подавляющая часть моего быдлокода вообще откажется собираться, либо же будет сплошное UB…

anonymous
()
Ответ на: комментарий от anonymous

В C++ есть точно такой же кусок про aliasing. При этом не считается, что он разрешает делать memcpy между объектами разных типов.

Значит в крестах есть что-то такое, что не позволяет полностью полагаться на п.6.5.7 в данном вопросе. Надо спрашивать у тех кто так не считает
Насколько я понимаю, в memcpy каждый символ интерпретируется, как unsigned char. А unsigned char может быть псевдонимом любого типа. Поэтому передача в memcpy данных разных типов, либо типов, отличных от unsigned char вполне законна и она выполнит работу, как надо
Проблемы могут быть с последующим использованием скопированных данных. Допустим программист не учел порядок байт и получил в size_pic совсем не то, что хотел. Вполне себе неопределенное поведение. Но это не траблы с выравниванием и не нарушение strict aliasing, последствия такого UB можно исправить в самом коде

tyro33
() автор топика
Ответ на: комментарий от anonymous

Твои детсадовские методы тут не пройдут
Отсутствие доказать невозможно

Ясно-понятно. Всего доброго

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.