Нашли или выдавили из себя код, который нельзя назвать нормальным,
на который без улыбки не взглянешь?
Не торопитесь его удалять или рефакторить, — запостите его на
говнокод.ру, посмеёмся вместе!
Тут они почти наверняка обосрались т.к. возможна невыровненная запись в память. Ну вот допустим
// push arg2
*p++ = 0x68;
*(INT32 *)p = arg2; // допустим что тут указатель делится на 4 и UB нет
p += 4; // тут он тоже делится на 4
#ifdef UNIX_X86_ABI
// mov eax, target
*p++ = 0xB8; // тогда тут он на 4 не делится
*(INT32 *)p = target; // а тут уже запись в хуйню по невыровненному адресу
Единственный вариант что тут они не обосрались - это если INT32 тип это хуйня с каким-то специальным атрибутом, что через него можно срать по невыровненным адресам. В ином случае это UB
А почему UB то? Разве не просто implementation defined? x86 так то срать на выравнивания если тебе не нужна атомарность. А для других процов этот код бесполезен, там свой будет.
Это видимо просто оговорка, что alignment у типа таков, сколько в нем байтов. Скажем, int на одной платформе из 4-х байт, а на другой може быть из 8-ми, и там alignment в первом случае будет 4, а во втором 8. Если у тебя на конкретной платформе для int известно, что у него alingof() равен 4, и ты тыкаешь указателем на int на не делящуийся на 4 адрес, то у тебя будет UB
В RISC процессорах нельзя обычно невыровненный доступ делать, а в x86 (который формально CISC, хотя это спорно) можно: за это просто пенальти прилетает.
CISC это более "высокоуровневые" процессоры.
Что вы в своем ВУЗе, архитектуру ЦПУ чтоли не проходили?
По-моему это хуйня. CISC и RISC это не про то, можно или нельзя делать невыровненный доступ, это про сложность инструкций. Можно и CISC сделать, чтоб там сигфолт происходил от невыровненного разыменования указателя.
Во-вторых (как я понимаю) пережить НЕ выровненный доступ сложно: нужно уметь высокоуровневую (ISA) инструкцию превратить в две низкоуровневых, заюзать внутренние буферы итд.*
CISC процессоры (в классическом понимании) чуть более умные, и могут себе такое позволить.
RISC обязаны быть тупыми и простыми как три копейки, и потому такое не делают.
зы: я путаю, или в каких-то древних PC невыровненный доступ фиксила чуть ли не внешняя логика в чипсете (которая делала два чтения в память)
*на самом деле там куча всяких инструкций микрокода, я понимабю
Вот тут упоминается мотороловский процессор 68000 который был CISC и при этом там была хуйня с сигфолтами от невыровненных доступов к памяти, но в чуть более новых процессорах такой хуйни уже не было:
> The original 68000 was a processor with two-byte granularity and lacked the circuitry to cope with unaligned addresses. When presented with such an address, the processor would throw an exception. The original Mac OS didn’t take very kindly to this exception, and would usually demand the user restart the machine. Ouch.
> Later processors in the 680×0 series, such as the 68020, lifted this restriction and performed the necessary work for you. This explains why some old software that works on the 68020 crashes on the 68000. It also explains why, way back when, some old Mac coders initialized pointers with odd addresses. On the original Mac, if the pointer was accessed without being reassigned to a valid address, the Mac would immediately drop into the debugger. Often they could then examine the calling chain stack and figure out where the mistake was.
https://govnokod.ru/25399
Такого же рода хуйню я находил, когда ковырялся в исходниках GHC. Правда там были не опкоды x86-64, а байткодная поебень для GHCi
А как правильно? Программа высирает код для CISC, в котором данные могут быть по любым адресам, в том числе и по нечётным. Нужно отказаться от записи слов, писать только по одному байту?
void putuint32(void *addr, uint32_t val)
{
typedef uint32_t uint32_t_unalign __attribute__ ((aligned (1)));
// так эта хуйня может указывать на невыровненый адрес
// хотя в атрибут можно еще какой-нибудь may_alias добавить на всякий случай
// от этой UB-хуйни всего можно ждать
uint32_t_unalign *ptr = (uint32_t_unalign *)addr;
*ptr = val;
}
x86 и позволяет misaligned access (если ты явно не заказал обратное), но может выдать за это пинальти (а может и не выдать, если данные уже в кеше, не?).
К счастью, сишка и кресты не завязаны на x86, потому мизалйнмент там UB: нужно явно месрать.
А петухи еще и на стрикт алиазинг положили (и кстати кастят в крестах сишным кастом, лошки), но царь в комментах уже объяснил, что если у него на машине всё рабоатет, то можно класть на стандарт
Царь Петух Первый
> This is legacy code on x86 only, where unaligned access is working on implementations.
Царь Петух Великий
> Every C/C++ compiler out there either does not enable strict aliasing optimizations by default, or has a switch to disable them.
Похоже на некоторых моих коллег, которые пишут код с рейсами потому что так быстрее.
Джей, а как тебя в .NET занесло-то, а? CLR на микроконтроллерах запустили?
ЗЫ: в комменты приглашается Гост/ISO, мне кажется он таких петухов оценит
Именно поэтому я за «Паскаль»: там каждая конструкция либо работает, либо выдаёт ошибку компиляции. Промежуточных состояний (вроде ворнингов и UB) в «Паскале» обычно не бывает. Правда, это ограничивает гибкость оптимизатора.
А потом появляются программы, которые не работают, если имя пользователя Windows начинается на букву «u». Это очень смешная ошибка, но у автора же всё работает.
В контроллерах подход "Works on my CPU" это вполне нормальная ситуация. Например, в таком-то контроллере ты можешь внутри аппаратного прерывания сделать некую хрень, в каком-то другом (более ранней и более поздней ревизии) это уже может быть нельзя делать (в документации при этом может быть как вообще нихуя не написано, так и написано, что работа такой-то хуйни не гарантируется, и может работать или не работать в зависимости от ревизии). Если тебе точно понятно, что в серию пойдет устройство с таким-то контроллером, вполне можно завязываться на такую хуйню.
Хотя тут конечно ньюанс есть. Если кто-то будет переносить это на другой контроллер, где какая-то хуйня перестает работать, его ждет багор
>в таком-то контроллере ты можешь внутри аппаратного прерывания сделать некую хрень, в каком-то другом
В x86 на многих ОС это норм тема.
Например ты не можешь из прерывания вытесниться (вызвав там page fault, например) потому что нужно быстро считать данные из буфера девайса.
Потому данные читают, и потом в фоне спокойно обрабатывают.
В softirq или taskletах в Linux.
В bottom half IRQ в BSD (в прыщах тоже так называлось давно-давно)
В DPC в Windows.
Предсавляю как они работают, приходит прыщавый задрот:
— Здравствуйте, посмотрите на фото этой девушки, хотите на ней женится?
(выкладывает на стол фото с порнхаба)
— Но это же Адриана Чечик, вы серьёзно?
— Вы на вопрос ответьте. Хотите?
— Ну, хотел бы...
— Отлично! Мы нашли её! С вас 400 т.р.
Единственный вариант что тут они не обосрались - это если INT32 тип это хуйня с каким-то специальным атрибутом, что через него можно срать по невыровненным адресам. В ином случае это UB
https://stackoverflow.com/questions/51126257/
3.9 Types
5. The alignment of a complete object type is an implementation-defined integer value representing a number of bytes.
Т.е. стандарт не утверждает, что uint32_t обязан быть выровнен на 4 байта, это реализация решает.
Сначала, 8.3, теперь 3.9
https://s.auto.drom.ru/i24227/pubs/26238/27087/2919753.svg
https://pzemtsov.github.io/2016/11/06/bug-story-alignment-on-x86.html
Suddenly, our x86 behaves just like RISC: it crashes when a pointer to uint32_t is not aligned by 4.
Какой багор )))
CISC это более "высокоуровневые" процессоры.
Что вы в своем ВУЗе, архитектуру ЦПУ чтоли не проходили?
Во-вторых (как я понимаю) пережить НЕ выровненный доступ сложно: нужно уметь высокоуровневую (ISA) инструкцию превратить в две низкоуровневых, заюзать внутренние буферы итд.*
CISC процессоры (в классическом понимании) чуть более умные, и могут себе такое позволить.
RISC обязаны быть тупыми и простыми как три копейки, и потому такое не делают.
зы: я путаю, или в каких-то древних PC невыровненный доступ фиксила чуть ли не внешняя логика в чипсете (которая делала два чтения в память)
*на самом деле там куча всяких инструкций микрокода, я понимабю
Вот тут упоминается мотороловский процессор 68000 который был CISC и при этом там была хуйня с сигфолтами от невыровненных доступов к памяти, но в чуть более новых процессорах такой хуйни уже не было:
> The original 68000 was a processor with two-byte granularity and lacked the circuitry to cope with unaligned addresses. When presented with such an address, the processor would throw an exception. The original Mac OS didn’t take very kindly to this exception, and would usually demand the user restart the machine. Ouch.
> Later processors in the 680×0 series, such as the 68020, lifted this restriction and performed the necessary work for you. This explains why some old software that works on the 68020 crashes on the 68000. It also explains why, way back when, some old Mac coders initialized pointers with odd addresses. On the original Mac, if the pointer was accessed without being reassigned to a valid address, the Mac would immediately drop into the debugger. Often they could then examine the calling chain stack and figure out where the mistake was.
так вот где порыта
В SSE есть две инструкции для одного и того же, но одна из них падает на невыровненных данных, как в RISC, а другая работает с любым указателем?
Такого же рода хуйню я находил, когда ковырялся в исходниках GHC. Правда там были не опкоды x86-64, а байткодная поебень для GHCi
Можно сделать особую функцию с memcpy
хотя такую функцию можно и по другому написать, например
или так
https://github.com/dotnet/runtime/issues/118602
Вот другие примеры:
> schadenfreude
Это, кстати, немецкое слово. Freude — радость, Schade — сожаление. Описывает странную эмоцию, когда человек смеётся над какими баграми.
https://en.m.wikipedia.org/wiki/Schadenfreude
https://arzamas.academy/mag/659-german_words
Да наш сайт целиком посвящён этому термину, оказывается.
g: avenue q shadenfredue
можешь почитать текст, или послушать арию. Офигенное же.
К счастью, сишка и кресты не завязаны на x86, потому мизалйнмент там UB: нужно явно месрать.
А петухи еще и на стрикт алиазинг положили (и кстати кастят в крестах сишным кастом, лошки), но царь в комментах уже объяснил, что если у него на машине всё рабоатет, то можно класть на стандарт
Царь Петух Первый
> This is legacy code on x86 only, where unaligned access is working on implementations.
Царь Петух Великий
> Every C/C++ compiler out there either does not enable strict aliasing optimizations by default, or has a switch to disable them.
Похоже на некоторых моих коллег, которые пишут код с рейсами потому что так быстрее.
Джей, а как тебя в .NET занесло-то, а? CLR на микроконтроллерах запустили?
ЗЫ: в комменты приглашается Гост/ISO, мне кажется он таких петухов оценит
Меня скорее забавляет что MS-петухи на серьезных щщах говорят:
1. Works on my CPU
1. Works on my Compiler
ну то-есть вот такого ждешь от ротоёба, но не от M$ же
Когда я в детстве говорил, что размер массива измеряется в интах, потмоу что это работает на моем борланд си под дос, то был не так уж и не прав
А потом появляются программы, которые не работают, если имя пользователя Windows начинается на букву «u». Это очень смешная ошибка, но у автора же всё работает.
Хотя тут конечно ньюанс есть. Если кто-то будет переносить это на другой контроллер, где какая-то хуйня перестает работать, его ждет багор
В x86 на многих ОС это норм тема.
Например ты не можешь из прерывания вытесниться (вызвав там page fault, например) потому что нужно быстро считать данные из буфера девайса.
Потому данные читают, и потом в фоне спокойно обрабатывают.
В softirq или taskletах в Linux.
В bottom half IRQ в BSD (в прыщах тоже так называлось давно-давно)
В DPC в Windows.
Иногда я залажу в реализации всяких таких хреней (типа HotSpot JVM, .NET runtime, GHC) и пытаюсь там найти такого рода багры
Мои подружки умирают! А вы там воду просто так льете!
https://i.postimg.cc/s1Fs2Rd6/image.png
— Здравствуйте, посмотрите на фото этой девушки, хотите на ней женится?
(выкладывает на стол фото с порнхаба)
— Но это же Адриана Чечик, вы серьёзно?
— Вы на вопрос ответьте. Хотите?
— Ну, хотел бы...
— Отлично! Мы нашли её! С вас 400 т.р.