#prog #cpp
От Chandler Carruth есть доклад "Garbage In, Garbage Out: Arguing about Undefined Behavior with nasal demons". В нём он рассказывает о конструктивных подходах к обсуждению UB и приводит примеры, как UB может сказаться на генерируемом коде.
В частности, на 39:19 он показывает пример со следующим кодом:
Переполнение же знаковых чисел является неопределённым поведением, и потому компилятор вправе полагаться на то, что переполнения не будет и не использовать модулярную арифметику. Чендлер прикладывает ассемблерный листинг для этих двух блоков кода, где индексы используются напрямую в адресном режиме
Из зала было справедливое замечание, что в данной ситуации правильнее было бы использовать
Звучит складно и вроде как вполне резонный аргумент в пользу UB для переполнения на интах. Так что я решил увидеть эффект своими глазами на godbolt.
И... Я его не увидел.
Более того, я решил написать вариант, где индексы
Код на godbolt
Эффект соблюдается и при увеличении числа блоков до шести.
В связи с этим у меня два вопроса:
1. Почему компилятор не эксплуатирует UB, связанное с переполнением знаковых чисел, и всё равно использует модулярную арифметику? (это вопрос скорее к GCC, потому что clang успешно проводит эту оптимизацию).
2. Почему и GCC, и clang не используют модулярную арифметику для
От Chandler Carruth есть доклад "Garbage In, Garbage Out: Arguing about Undefined Behavior with nasal demons". В нём он рассказывает о конструктивных подходах к обсуждению UB и приводит примеры, как UB может сказаться на генерируемом коде.
В частности, на 39:19 он показывает пример со следующим кодом:
bool compare(uint32_t i1, uint32_t i2,
uint8_t* block) {
uint8_t c1, c2;
/* 1 */
c1 = block[i1]; c2 = block[i2];
if (c1 != c2) return c1 > c2;
i1++; i2++;
/* 2 */
c1 = block[i1]; c2 = block[i2];
if (c1 != c2) return c1 > c2;
i1++; i2++;
...
Код генерировался под 64-битную платформу. По словам Чендлера, проблема заключается в том, что индексы имеют беззнаковый тип. В C и C++ переполнение беззнаковых чисел определено и имеет модулярную семантику. Это сказывается на генерируемом коде: во втором блоке сначала происходит вычисление нужного смещения через lea
— которое приведёт индекс к нулю при переполнении — и только потом индекс используется в mov
для доступа к памяти. Переполнение же знаковых чисел является неопределённым поведением, и потому компилятор вправе полагаться на то, что переполнения не будет и не использовать модулярную арифметику. Чендлер прикладывает ассемблерный листинг для этих двух блоков кода, где индексы используются напрямую в адресном режиме
mov
и не проходят через модулярную арифметику.Из зала было справедливое замечание, что в данной ситуации правильнее было бы использовать
size_t
. Чендлер на это ответил довольно развёрнуто, но одним из пунктов в его ответе было то, что size_t
— беззнаковый тип и потому страдает от той же пессимизации кода.Звучит складно и вроде как вполне резонный аргумент в пользу UB для переполнения на интах. Так что я решил увидеть эффект своими глазами на godbolt.
И... Я его не увидел.
Более того, я решил написать вариант, где индексы
i1
и i2
имели тип size_t
. И в этом якобы неэффективном варианте модулярной арифметики не было.Код на godbolt
Эффект соблюдается и при увеличении числа блоков до шести.
В связи с этим у меня два вопроса:
1. Почему компилятор не эксплуатирует UB, связанное с переполнением знаковых чисел, и всё равно использует модулярную арифметику? (это вопрос скорее к GCC, потому что clang успешно проводит эту оптимизацию).
2. Почему и GCC, и clang не используют модулярную арифметику для
size_t
, не смотря на то, что это, вообще говоря, смена наблюдаемого поведения? У меня есть предположение, что это связано с переполнением указателей, которое тоже является UB (переполнение любой инкрементации означало бы, что читается память по указателю block + SIZE_MAX
, а чтение по такому указателю не является валидным, поскольку все объекты в памяти не больше SIZE_MAX
по определению и указатель, сформированный таким образом, будет one past end даже самого большого объекта).YouTube
CppCon 2016: Chandler Carruth “Garbage In, Garbage Out: Arguing about Undefined Behavior..."
https://CppCon.org
—
Presentation Slides, PDFs, Source Code and other presenter materials are available at: https://github.com/cppcon/cppcon2016
—
There has been an overwhelming amount of tension in the programming world over the last year due to something…
—
Presentation Slides, PDFs, Source Code and other presenter materials are available at: https://github.com/cppcon/cppcon2016
—
There has been an overwhelming amount of tension in the programming world over the last year due to something…
🤔3👍1
Forwarded from Денис Чужой про комедию
С раннего утра наблюдаю за тем, как пользователи твиттера советуют человеку книги лучше, чем «Атлант расправил плечи»
👌8😁4❤2👎1🤡1
shitposting 3.0 [+ dragons]
Photo
Ответственно заявляю, что я к воспитанию поколения тиктока не имею отношения
❤6👍4🔥1😁1
Forwarded from dd if=/dev/stuff of=/dev/tg
https://twitter.com/zack_overflow/status/1715042340514017559 — Flappy Bird на тайплевеле тайпскрипта.
Это стало возможным благодаря кастомному рантайм, написанному на Zig.
A work of pure art 🖼️
Это стало возможным благодаря кастомному рантайм, написанному на Zig.
A work of pure art 🖼️
X (formerly Twitter)
zack (in SF) (@zack_overflow) on X
I wrote a 2D game, entirely in type-level Typescript.
Yes, you read that right. This is flappy bird, written only in Typescript types.
How did I do it? It involves a lot of type magic, and a new type-level Typescript runtime I made in Rust + Zig.
Let me…
Yes, you read that right. This is flappy bird, written only in Typescript types.
How did I do it? It involves a lot of type magic, and a new type-level Typescript runtime I made in Rust + Zig.
Let me…
😱7❤2🔥1😁1
Forwarded from dd if=/dev/stuff of=/dev/tg
dd if=/dev/stuff of=/dev/tg
https://twitter.com/zack_overflow/status/1715042340514017559 — Flappy Bird на тайплевеле тайпскрипта. Это стало возможным благодаря кастомному рантайм, написанному на Zig. A work of pure art 🖼️
И чуть более развернутый пост от автора: https://zackoverflow.dev/writing/flappy-bird-in-type-level-typescript
zackoverflow.dev
Flappy Bird Implemented in Typescript types
The ultimate type-level trickery
Подписчики, а какие вы знаете IDL (interface definition languages) с поддержкой сумм-типов?