netch80: (bird)
[personal profile] netch80
Дискуссия прошла в Fido, пересмотрел - думаю, стоит сделать копию в чём-то индексируемом.

= su.c_cpp (2:463/68.300) ========================================== su.c_cpp =
 Msg  : 1 из 191
 От   : Valentin Nechayev                   2:5020/400      20 окт 14, 10:27
 Кому : All                                                 20 окт 14, 11:09
 Тема : UB reasoning
===============================================================================


Статья с попыткой обоснования нынешнего широкого применения "undefined
behavior" в стандартах C/C++.
http://habrahabr.ru/post/230777/
Комментарии (и раскрытие позиции автора в них) не менее интересны, чем
сама статья. (Основная дискуссия вроде уже утихла.)
--- ifmail v.2.15dev5.4
 * Origin: Dark side of coredump (2:5020/400)

= su.c_cpp (2:463/68.300) ========================================== su.c_cpp =
 Msg  : 2 из 191                            Rcv
 От   : Stanislav Kiselev                   2:5020/2140.486 20 окт 14, 14:41
 Кому : Valentin Nechayev                                   22 окт 14, 14:12
 Тема : UB reasoning
===============================================================================
Привет, Valentin!

Ответ на письмо датированное <20 окт 14>, Valentin Nechayev -> All:
Вот интересно когда такие статьи будут появляться вначале в фидо, а патом уже 
на всяких харабарах ))

А так, приведенный пример вполне имеет место быть в проге на чистом си ( где 
широко используются глобальные переменные) и неявно может быть переаллоцирована
память и переприсвоены значения, что найти без профилировщика действительно 
сложно. Еще он не написал, что HЕ есть хороший способ подглядывать асмовский 
выхлоп и на его основе подстраивать свой код.

С наилучшими пожеланиями, Stanislav.

--- -Пиши, старик, пиши! Мы тебя не покинем.
 * Origin: Hеужели опять: яйца всмятку, котлеты, цыплята? (2:5020/2140.486)

= su.c_cpp (2:463/68.300) ========================================== su.c_cpp =
 Msg  : 3 из 191
 От   : Eugene Muzychenko                   2:5000/14       20 окт 14, 23:54
 Кому : Stanislav Kiselev                                   22 окт 14, 14:12
 Тема : UB reasoning
===============================================================================
Привет!

20 Oct 14 14:41, you wrote to Valentin Nechayev:

 SK> Вот интересно когда такие статьи будут появляться вначале в фидо, а
 SK> патом уже на всяких харабарах ))

Разумеется, никогда. Ибо смысла нет.

Всего доброго!
Евгений Музыченко
eu-gene@muzy-chen-ko.net (все дефисы убрать)

--- GoldED+/W32-MSVC 1.1.5-b20130111
 * Origin: Fox Tracks, Novosibirsk, Russia (2:5000/14)

= su.c_cpp (2:463/68.300) ========================================== su.c_cpp =
 Msg  : 4 из 191                            Rcv
 От   : Serguei E. Leontiev                 2:5020/400      21 окт 14, 06:11
 Кому : Valentin Nechayev                                   22 окт 14, 14:12
 Тема : Re: UB reasoning
===============================================================================
@Realname: Сергей Ефимович Леонтьев

Привет Валентин,

От 20 октября 2014 г., 10:27:35 в fido7.su.c-cpp ты писал:

 VN> Статья с попыткой обоснования нынешнего широкого применения
 VN> "undefined behavior" в стандартах C/C++.
 VN> http://habrahabr.ru/post/230777/

Прикольно, наверное, надо бы там вставить пару комментариев. Да вот
беда, я там не зарегистрирован.

 VN> Комментарии (и раскрытие позиции автора в них) не менее
 VN> интересны, чем сама статья. (Основная дискуссия вроде уже
 VN> утихла.)

Лично у меня создалось впечатление, что ищут UB языка C там, где его
нет. Исходя из текста стандарта ISO/IEC 9899:2011 (C11), п. 6.7.3.1,
EXAMPLE 4, UB может быть вот у такого кода:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int * restrict p;
    int * restrict q;

    p = (int*)malloc(sizeof(int));
    q = p; // или похожее (int*)realloc(p, sizeof(int));
    *p = 1;
    *q = 2;
    if(p == q) {
        printf("%d %d\n", *p, *q);
    }
    return 0;
}

А то, что clang творит на пустом месте, без restrict, это не UB для C11,
это просто ничем не регламентированное безобразие.

--
Успехов, Сергей Леонтьев. E-mail: lse@CryptoPro.ru   
--- ifmail v.2.15dev5.4
 * Origin: ГАИШ МГУ (2:5020/400)

= su.c_cpp (2:463/68.300) ========================================== su.c_cpp =
 Msg  : 5 из 191
 От   : Valentin Nechayev                   2:5020/400      21 окт 14, 09:35
 Кому : "Serguei E. Leontiev"                               22 окт 14, 14:12
 Тема : Re: UB reasoning
===============================================================================


>>> Serguei E. Leontiev wrote: 

SEL> Лично у меня создалось впечатление, что ищут UB языка C там, где его
SEL> нет. Исходя из текста стандарта ISO/IEC 9899:2011 (C11), п. 6.7.3.1,
SEL> EXAMPLE 4, UB может быть вот у такого кода:

SEL> #include <stdio.h>
SEL> #include <stdlib.h>

SEL> int main()
SEL> {
SEL>     int * restrict p;
SEL>     int * restrict q;

SEL>     p = (int*)malloc(sizeof(int));
SEL>     q = p; // или похожее (int*)realloc(p, sizeof(int));

Это таки разные случаи. С копированием указателя старый сохраняется,
а в случае realloc старый гарантированно нельзя использовать,
независимо от restrict. В данном примере, да, диверсия за счёт другого
указателя на restrict объект, но она присутствует при копировании, но
уже не при realloc (при realloc начинает быть неверным другое -
присвоение *p).

SEL> А то, что clang творит на пустом месте, без restrict, это не UB для C11,
SEL> это просто ничем не регламентированное безобразие.

Я бы не возражал, если бы не
1) Формальный факт наличия у авторов компилятора априорно большей
компетенции (или, как модно говорить в 5020, экспертизы), который
требует некоторой аргументации в возражениях:)
2) Того факта, что практически все "пост-классические" компиляторы
сейчас пытаются проявить собственную гибкость в понимании UB и
сокращении странностей; вот пример, где gcc ещё активнее clang:
http://rsdn.org/forum/cpp/5653418.all
недавно с удивлением увидел, что сборка Python по умолчанию идёт с -O3
-fwrapv (!) (не только в отдельных местах, где им была бы
принципиально важна арифметика в дополнительном коде)

и третья альтернатива в виде open64 работает совсем по-своему, но тоже
с выходками в неожиданных местах...


--netch--
--- ifmail v.2.15dev5.4
 * Origin: Dark side of coredump (2:5020/400)

= su.c_cpp (2:463/68.300) ========================================== su.c_cpp =
 Msg  : 6 из 191                            Rcv
 От   : Serguei E. Leontiev                 2:5020/400      21 окт 14, 22:05
 Кому : Valentin Nechayev                                   22 окт 14, 14:12
 Тема : Re: UB reasoning
===============================================================================
@Realname: Сергей Ефимович Леонтьев

Привет Валентин,

От 21 октября 2014 г., 9:35:00 в fido7.su.c-cpp ты писал:

 ??>>>> Serguei E. Leontiev wrote:
 SEL>> Лично у меня создалось впечатление, что ищут UB языка C
 SEL>> там, где его нет. Исходя из текста стандарта ISO/IEC
 SEL>> 9899:2011 (C11), п. 6.7.3.1, EXAMPLE 4, UB может быть вот
 SEL>> у такого кода:
 VN>
 SEL>> #include <stdio.h>
 SEL>> #include <stdlib.h>
 VN>
 SEL>> int main()
 SEL>> {
 SEL>>     int * restrict p;
 SEL>>     int * restrict q;
 VN>
 SEL>>     p = (int*)malloc(sizeof(int));
 SEL>>     q = p; // или похожее (int*)realloc(p, sizeof(int));
 VN>
 VN> Это таки разные случаи. С копированием указателя старый
 VN> сохраняется, а в случае realloc старый гарантированно нельзя
 VN> использовать, независимо от restrict. В данном примере, да,
 VN> диверсия за счёт другого указателя на restrict объект, но она
 VN> присутствует при копировании, но уже не при realloc (при
 VN> realloc начинает быть неверным другое - присвоение *p).

Мда, это я лопухнулся, прочитал в статье спорное утверждение:
"...Заметьте: запрещено не наличие двух указателей на объекты разных
типов...", и меня понесло.

А в приведённом примере, таки да наблюдается явная зависимость
результата от "-fno-builtin".

 SEL>> А то, что clang творит на пустом месте, без restrict, это
 SEL>> не UB для C11, это просто ничем не регламентированное
 SEL>> безобразие.
 VN> Я бы не возражал, если бы не
 VN> 1) Формальный факт наличия у авторов компилятора априорно
 VN> большей компетенции (или, как модно говорить в 5020,
 VN> экспертизы), который требует некоторой аргументации в
 VN> возражениях:)

Это действительно связано со встроенной реализацией realloc(), но
аргументация на счёт того ошибка это или UB, неубедительная. Покажите
мне здесь строчку с намёком на UB:
int main()
{
    int *p;
    int *q;

    p = (int*)malloc(sizeof(int));
    if(NULL == p) {
        return 1;
    }
    q = (int*)realloc(p, sizeof(int));
    if(NULL == q) {
        return 1;
    }
    *q = 2;
    if(p == q) {
        *p = 1;
        printf("%d %d\n", *p, *q);
    }
    return 0;
}

--
Успехов, Сергей Леонтьев. E-mail: lse@CryptoPro.ru   
--- ifmail v.2.15dev5.4
 * Origin: ГАИШ МГУ (2:5020/400)

= su.c_cpp (2:463/68.300) ========================================== su.c_cpp =
 Msg  : 7 из 191                            Rcv
 От   : Serguei E. Leontiev                 2:5020/400      22 окт 14, 02:05
 Кому : Valentin Nechayev                                   22 окт 14, 14:12
 Тема : Re: UB reasoning
===============================================================================
@Realname: Сергей Ефимович Леонтьев

Привет Валентин,

От 21 октября 2014 г., 9:35:00 в fido7.su.c-cpp ты писал:

 VN> возражениях:) 2) Того факта, что практически все
 VN> "пост-классические" компиляторы сейчас пытаются проявить
 VN> собственную гибкость в понимании UB и сокращении странностей;
 VN> вот пример, где gcc ещё активнее clang:
 VN> http://rsdn.org/forum/cpp/5653418.all недавно с удивлением

:) О как! Теперь gcc в версиях 4.8, 4.9, а может быть и выше, стали
предполагать, что программисты перестали делать ошибки? Класс! Мало
того, отладочная печать - это тоже не для пользователей gcc (типа
используйте dtrace, gdb, dbx и прочая, прочая, ну-ну).

А иначе, как объяснить "логические" выводы, что из того выдаётся
выражение i*1000000000, следует отсутствие в нём переполнения и следует,
что -2<=i<=2.

 VN> увидел, что сборка Python по умолчанию идёт с -O3 -fwrapv (!)

Дык, когда-то считывалось, что в `-O2' входят только "безопасные"
оптимизации, так что модули ядра с ним собирать можно. А сейчас, флаг
`-O2' у 4.8 и 4.9 сносит крышу. Так что для gcc без `-fwrapv' теперь
нельзя, а особой разницы между `-O2' и `-O3' выходит, что и нет.

А что реальным параноикам clang говорить, это пока вопрос.

 VN> и третья альтернатива в виде open64 работает совсем по-своему,
 VN> но тоже с выходками в неожиданных местах...

Слыхал я про Intel и PGI, они правда, FreeBSD не очень любят, и Oracle,
это даже Mac OSX не уважает.

Да и модули ядра, я всегда считал, надо собирать "штатным" компилятором.
Hо сейчас у меня стали возникать сомнения на счёт некоторых "штатных"
компиляторов.

--
Успехов, Сергей Леонтьев. E-mail: lse@CryptoPro.ru   
--- ifmail v.2.15dev5.4
 * Origin: ГАИШ МГУ (2:5020/400)

= su.c_cpp (2:463/68.300) ========================================== su.c_cpp =
 Msg  : 8 из 191
 От   : Valentin Nechayev                   2:5020/400      22 окт 14, 09:35
 Кому : "Serguei E. Leontiev"                               22 окт 14, 14:12
 Тема : Re: UB reasoning
===============================================================================


>>> Serguei E. Leontiev wrote: 

 VN>> http://rsdn.org/forum/cpp/5653418.all недавно с удивлением
SEL> :) О как! Теперь gcc в версиях 4.8, 4.9, а может быть и выше, стали
SEL> предполагать, что программисты перестали делать ошибки? Класс!

Почему только в gcc и только с 4.8? Собственно ссылка, с которой я
начал этот тред, как раз говорит про то, что ошибка программиста может
приводить к UB. Hо чем такая ошибка хуже любой другой ошибки?
По-моему, присвоение с порчей чужой памяти по забытому указателю
отлаживается на порядки сложнее, чем хохмы арифметики.

SEL> Мало
SEL> того, отладочная печать - это тоже не для пользователей gcc (типа
SEL> используйте dtrace, gdb, dbx и прочая, прочая, ну-ну).
SEL> А иначе, как объяснить "логические" выводы, что из того выдаётся
SEL> выражение i*1000000000, следует отсутствие в нём переполнения и следует,
SEL> что -2<=i<=2.

Hу тут я не соглашусь. При отладочной печати надо выводить i, а не
i*1000000000. Причём выводить предельно осторожно, проверив, что это i
имеет смысл. Или же, таки да, делать отладку чем-то внешним.:)

Вообще тема этой арифметики, похоже, никогда не остановится. Hапример,
почитайте про стандарты серии language independent arithmetic (LIA) от
ISO и прочих. Их никто в окружающем меня мире даже не думал
использовать, но сама по себе задумка стандартизовать и "пусть лежит,
стыдит и глаза мозолит" в чём-то достойная. А вот чего можно было
достаточно быстро сделать уже к следующему релизу стандарта - это
решение в подражание C# checked/unchecked с синтаксическими
контекстами кода, где-то так:

"[["<specifier>"]]" ("("<expression>")"|"{"<block_body>"}")

например

    int a, b, c;
    <...>
    a = [[tc_int]](b + c);

с вариантами спецификаторов:
- relaxed_int - как сейчас в стандарте - для знаковых переполнение -
  UB, для беззнаковых - по модулю 2**N;
- tc_int (от "truncated complement" или "two's complement") - остаётся
  младшая часть для дополнительного кода (как при -fwrapv или в Яве);
- platform_native_int - максимально родное и эффективное для платформы
  (и если выдаст исключение, как в MIPS для команд add, sub - проблемы
  автора кода);
- checked_int - любое переполнение генерирует сигнал (для C++ -
  исключение);
- checked_flag_int($varname) - любое переполнение или нарушение типа
  деления на 0 выставляет в $varname ненулевое значение;
- saturated_int - переполнение вызывает оставление крайнего значения,
  ближайшего к несохраняемому результату.

Определить заголовочник с макросами для проверки поддержки конкретного
режима, оставить relaxed_int в обязательной части, а остальные - в
рекомендуемой, и проблема решена надолго.  Естественно, не все
реализации будут эффективны везде, но это снова проблема автора кода.
Подумать про меры по воздействию этого на импортированные из далёких
мест макросы (может, для них не использовать этот контекст).

В gcc начиная где-то с 4.4 проблема частично решается (только для
варианта tc_int) на уровне отдельных функций (а за счёт inline -
достаточно эффективно) через function attribute "optimize" или его
собственные прагмы с той же ролью. Hо это откровенно локальные хаки.

 VN>> увидел, что сборка Python по умолчанию идёт с -O3 -fwrapv (!)

SEL> Дык, когда-то считывалось, что в `-O2' входят только "безопасные"
SEL> оптимизации, так что модули ядра с ним собирать можно. А сейчас, флаг
SEL> `-O2' у 4.8 и 4.9 сносит крышу. Так что для gcc без `-fwrapv' теперь
SEL> нельзя, а особой разницы между `-O2' и `-O3' выходит, что и нет.

SEL> А что реальным параноикам clang говорить, это пока вопрос.

clang поддерживает все публичные gcc'шные ключи, если вопрос об этом.
То есть тот же -fwrapv для него работает. Хотя потребность в нём
возникает раньше (кажется, уже при -O).

 VN>> и третья альтернатива в виде open64 работает совсем по-своему,
 VN>> но тоже с выходками в неожиданных местах...
SEL> Слыхал я про Intel и PGI, они правда, FreeBSD не очень любят, и Oracle,
SEL> это даже Mac OSX не уважает.

Hу я специально назвал только свободные для коммерческого
использования.

SEL> Да и модули ядра, я всегда считал, надо собирать "штатным" компилятором.
SEL> Hо сейчас у меня стали возникать сомнения на счёт некоторых "штатных"
SEL> компиляторов.

Так известно же, что каждый подъём проверяемой версии gcc при сборке
linux приводит к массе правок багов как в linux, так и в gcc.:)
С остальными аналогично.


--netch--
--- ifmail v.2.15dev5.4
 * Origin: Dark side of coredump (2:5020/400)

= su.c_cpp (2:463/68.300) ========================================== su.c_cpp =
 Msg  : 9 из 191                            Rcv
 От   : Serguei E. Leontiev                 2:5020/400      24 окт 14, 20:32
 Кому : Valentin Nechayev                                   26 окт 14, 22:25
 Тема : Re: UB reasoning
===============================================================================
@Realname: Сергей Ефимович Леонтьев

Привет Валентин,

От 22 октября 2014 г., 9:35:17 в fido7.su.c-cpp ты писал:

 VN>
 ??>>>> Serguei E. Leontiev wrote:
 VN>
 VN>>> http://rsdn.org/forum/cpp/5653418.all недавно с
 VN>>> удивлением
 SEL>> :) О как! Теперь gcc в версиях 4.8, 4.9, а может быть и
 SEL>> выше, стали предполагать, что программисты перестали
 SEL>> делать ошибки? Класс!
 VN> Почему только в gcc и только с 4.8? Собственно ссылка, с

В этой, близкой к богопротивной, деятельности gcc ранее замечен не был.

 VN> которой я начал этот тред, как раз говорит про то, что ошибка
 VN> программиста может приводить к UB. Hо чем такая ошибка хуже
 VN> любой другой ошибки?

М-м-м, заметим, есть нюанс. Поясню, по моему глубокому убеждению, любая
программа подавляющую часть своего жизненного цикла (ВСЕГДА) содержала,
содержит и будет содержать множество разнообразных ошибок, т.е. наличие
множества трасс исполнения, которые нарушают инварианты прикладных
требований, которые приводят к отсутствию взаимодействия с внешним миром
(зацикливание, это же то же UB, но в стандарте его просто забыли
поименовать), так и таких, которые приводят к иным UB упомянутым в
стандарте. Единственно, что мы можем сделать, это разными путями снизить
вероятность возникновения этих UB, а так же снизить вредоносность
вероятных последствий этих UB.

А оптимизатор gcc исходит из обратного, опирается на предположение об
отсутствии UB:
- поэтому целого переполнения быть не может, поэтому выполняются те или
иные ограничения, поэтому можно вырезать или видоизменить то-то и это,
поэтому ...;
- поэтому обращения к нулевому указателю быть не может, поэтому
неизвестно кто и как, но обязательно вызовет функцию CallNever(),
поэтому указателю будет присвоено именно то значение, которое
оптимизатор увидел в данный, конкретный момент, поэтому...;
- поэтому выхода за границы массива, а может даже массива в union, быть
не может...;

ИМХО, это противоречит, классическому определению UB, т.е. мы не
определяем, что произойдет, но что-то произойдёт: получится NaN или
"бесконечность", возникнет сигнал или программа прервёт свое исполнение.

А оптимизатор gcc нарушает принцип причинности.

 VN> По-моему, присвоение с порчей чужой памяти
 VN> по забытому указателю отлаживается на порядки сложнее, чем
 VN> хохмы арифметики.
 SEL>> Мало
 SEL>> того, отладочная печать - это тоже не для пользователей
 SEL>> gcc (типа используйте dtrace, gdb, dbx и прочая, прочая,
 SEL>> ну-ну). А иначе, как объяснить "логические" выводы, что из
 SEL>> того выдаётся выражение i*1000000000, следует отсутствие в
 SEL>> нём переполнения и следует, что -2<=i<=2.
 VN> Hу тут я не соглашусь. При отладочной печати надо выводить i, а
 VN> не i*1000000000. Причём выводить предельно осторожно, проверив,
 VN> что это i имеет смысл. Или же, таки да, делать отладку чем-то
 VN> внешним.:)

Проблема же не только и не столько в печати или в арифметике, но в
принципе "Если Бога нет, то всё позволено".

 VN> Вообще тема этой арифметики, похоже, никогда не остановится.
 VN> Hапример, почитайте про стандарты серии language independent
 VN> arithmetic (LIA) от ISO и прочих. Их никто в окружающем меня
 VN> мире даже не думал использовать, но сама по себе задумка
 VN> стандартизовать и "пусть лежит, стыдит и глаза мозолит" в
 VN> чём-то достойная. А вот чего можно было достаточно быстро
 VN> сделать уже к следующему релизу стандарта - это решение в
 VN> подражание C# checked/unchecked с синтаксическими контекстами
 VN> кода, где-то так:
 VN> "[["<specifier>"]]"
 VN> ("("<expression>")"|"{"<block_body>"}")
 VN> например
 VN>
 VN>     int a, b, c;
 VN> ??<...>
 VN>     a = [[tc_int]](b + c);
 VN>
 VN> с вариантами спецификаторов:
 VN> - relaxed_int - как сейчас в стандарте - для знаковых
 VN> переполнение -   UB, для беззнаковых - по модулю 2**N;
 VN> - tc_int (от "truncated complement" или "two's complement") -
 VN> остаётся   младшая часть для дополнительного кода (как при
 VN> -fwrapv или в Яве); - platform_native_int - максимально родное
 VN> и эффективное для платформы   (и если выдаст исключение, как в
 VN> MIPS для команд add, sub - проблемы   автора кода);
 VN> - checked_int - любое переполнение генерирует сигнал (для C++ -
 VN>   исключение);
 VN> - checked_flag_int($varname) - любое переполнение или нарушение
 VN> типа   деления на 0 выставляет в $varname ненулевое значение;
 VN> - saturated_int - переполнение вызывает оставление крайнего
 VN> значения,   ближайшего к несохраняемому результату.
 VN>
 VN> Определить заголовочник с макросами для проверки поддержки
 VN> конкретного режима, оставить relaxed_int в обязательной части,
 VN> а остальные - в рекомендуемой, и проблема решена надолго.
 VN> Естественно, не все реализации будут эффективны везде, но это
 VN> снова проблема автора кода. Подумать про меры по воздействию
 VN> этого на импортированные из далёких мест макросы (может, для
 VN> них не использовать этот контекст).
 VN> В gcc начиная где-то с 4.4 проблема частично решается (только
 VN> для варианта tc_int) на уровне отдельных функций (а за счёт
 VN> inline - достаточно эффективно) через function attribute
 VN> "optimize" или его собственные прагмы с той же ролью. Hо это
 VN> откровенно локальные хаки.

Только вот, т.к. исходно открытые мозги UB читают не так, как обычно, то
relaxed_int - implementation defined.

 VN>>> увидел, что сборка Python по умолчанию идёт с -O3
 VN>>> -fwrapv (!)
 SEL>> Дык, когда-то считывалось, что в `-O2' входят только
 SEL>> "безопасные" оптимизации, так что модули ядра с ним
 SEL>> собирать можно. А сейчас, флаг `-O2' у 4.8 и 4.9 сносит
 SEL>> крышу. Так что для gcc без `-fwrapv' теперь нельзя, а
 SEL>> особой разницы между `-O2' и `-O3' выходит, что и нет.
 SEL>> А что реальным параноикам clang говорить, это пока вопрос.
 VN> clang поддерживает все публичные gcc'шные ключи, если вопрос об
 VN> этом. То есть тот же -fwrapv для него работает. Хотя
 VN> потребность в нём возникает раньше (кажется, уже при -O).

Для проблемы UB в целом одного `-fwrapv' недостаточно.

 VN>>> и третья альтернатива в виде open64 работает совсем
 VN>>> по-своему, но тоже с выходками в неожиданных местах...
 SEL>> Слыхал я про Intel и PGI, они правда, FreeBSD не очень
 SEL>> любят, и Oracle, это даже Mac OSX не уважает.
 VN> Hу я специально назвал только свободные для коммерческого
 VN> использования.

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

 SEL>> Да и модули ядра, я всегда считал, надо собирать "штатным"
 SEL>> компилятором. Hо сейчас у меня стали возникать сомнения на
 SEL>> счёт некоторых "штатных" компиляторов.
 VN> Так известно же, что каждый подъём проверяемой версии gcc при
 VN> сборке linux приводит к массе правок багов как в linux, так и в
 VN> gcc.:) С остальными аналогично.

Ошибки правят, а UB напротив, холят и лелеют. Подозреваю, что ошибку
оптимизации встроенного realloc() в clang уже рапортовали, но
разбираться не стали, просто объявили UB.

--
Успехов, Сергей Леонтьев. E-mail: lse@CryptoPro.ru   
--- ifmail v.2.15dev5.4
 * Origin: ГАИШ МГУ (2:5020/400)

= su.c_cpp (2:463/68.300) ========================================== su.c_cpp =
 Msg  : 10 из 191
 От   : Valentin Nechayev                   2:5020/400      27 окт 14, 09:25
 Кому : "Serguei E. Leontiev"                               27 окт 14, 17:43
 Тема : Re: UB reasoning
===============================================================================


>>> Serguei E. Leontiev wrote: 

 SEL>>> :) О как! Теперь gcc в версиях 4.8, 4.9, а может быть и
 SEL>>> выше, стали предполагать, что программисты перестали
 SEL>>> делать ошибки? Класс!
 VN>> Почему только в gcc и только с 4.8? Собственно ссылка, с
SEL> В этой, близкой к богопротивной, деятельности gcc ранее замечен не был.

Замечался. Хотя в 4.8 были активизированы новые возможности, которые
привели к более частым эффектам (типа
-faggressive-loop-optimizations). Принципиально же они это стали
допускать ещё с 3-х версий.

SEL> Проблема же не только и не столько в печати или в арифметике, но в
SEL> принципе "Если Бога нет, то всё позволено".

Мнэээ... я тут принципиально не соглашусь. Дело не в принципе как
таковом, хотя он сформулирован очень оригинально:)
Дело в идее оптимизации как таковой.

Я тут начал рисовать несколько примеров, но остановился - думаю,
примеры Вы и сами наберёте. Тут было повторение одного и того же
выражения дважды (намёк на volatile), и умножение матриц (целая
цепочка оптимизаций вроде выноса общих подвыражений для указателя при
индексации, замены умножения на переменную цикла - сложением смещения,
которое параллельно этой переменной...), и простейшая оптимизация
константного выражения, и ещё можно было бы много придумывать. Hо
любая оптимизация - это сделанное компилятором _изменение_
сгенерированного им кода по сравнению с тем, что поступило от
программиста.

Вопрос, таким образом, превращается в практически гамлетовский "менять
или не менять?" по каждому мельчайшему пункту. Менять b=a; c=a на
c=b=a это нарушит логику программиста, или нет? Замена (a+c)>(b+c) на

(a>b) это нарушит логику программиста, или нет? От чего это зависит,

как понять компилятору, на что он имеет право, а на что - нет?

Как известно из ТРИЗ, если есть противоречие, надо его разрешать во
времени или в пространстве. У нас есть рычаги для такого разрешения?
Оказывается, есть. Это управление уровнем оптимизации. Само по себе
разрешение оптимизации на достаточно высоком уровне (например,
пресловутый -O2) уже означает _явное_ разрешение компилятору
думать, что да, "бога" выше его - нет. Только я бы понимал "бог" в его
исходном понятии "сила, власть", как английское power, откуда
"богатство", "богатырь" и т.д. - компилятору даётся право считать себя
силой по отношению к коду и от этого делать более продвинутые выводы:)
К вопросу о моральном авторитете это не имеет отношения, а вот то,
какие в среднем по больнице (включая морг и крематорий) оптимизации
подобного рода нужны и допустимы - это уже вопрос компетенции
("экспертизы", согласно московскому жаргону) авторов компилятора.

Если все эти супервозможности не нравятся, можно сократить оптимизации
до -O1 или отключать попунктно. Всё равно потребуется какая-то
платформенно-зависимая заточка...

Вот что мне не нравится в подходе вокруг стандарта это именно то, что
они _слишком_ затачиваются на "паршиво усредним, зато всем будет
приблизительно равно эффективно" без предоставления штатных средств
сделать полезно для 90% встреченного парка (x86+ARM+MIPS), пусть это и
не будет работать на оставшихся 10%.

 VN>> - relaxed_int - как сейчас в стандарте - для знаковых
 VN>> переполнение -   UB, для беззнаковых - по модулю 2**N;

SEL> Только вот, т.к. исходно открытые мозги UB читают не так, как обычно, то
SEL> relaxed_int - implementation defined.

В случае знакового переполнения - так и есть, потому что
implementation defined это частный случай UB :)

SEL> Для проблемы UB в целом одного `-fwrapv' недостаточно.

Я и не говорил, что достаточно. Hо явно залагаются они только на тему
знаковой арифметики.

 VN>> Hу я специально назвал только свободные для коммерческого
 VN>> использования.

SEL> Возможно, мы имеем реализацию принципа "бесплатный сыр бывает только в
SEL> мышеловках", тем более, что сыр не так уж и дорог.

Любая цена за сыр, отличная от цены на tar xjpf для бинарного кода,
будет неподъёмной, когда предполагается жизнь компилятора на каждой
второй домашней установке хотя бы из-за необходимости собрать по месту
хитрые модули к ядру:) Я понимаю, что в случае ситуации "компилятор -
это то, что начинается от 1000$" отрасль нашла бы другое решение, но
сама по себе возможность решений вида "попробовать - это стоит только
времени, но не денег", как только закрепилась в каких-то процессах,
стала неустранимой. И, ящетаю, это правильно.

SEL> У меня возникло
SEL> ощущение, что свободные программисты начали соревнование, кто быстрее
SEL> скомпилирует и выполнит STL, а простых людей посылают в UB. Так что,
SEL> быть может, не надо обновлять gcc, а надо мигрировать на нечто, более
SEL> надёжное.

"Миграция" такого рода на сейчас делается простейшим методом:
%s/-O2/-O1/g

можно, конечно, и попунктно, но в целом я не вижу считать проблему
существенной. Коммерческий код и так для конкретной версии жёстко
фиксирует и компилятор, и опции сборки.

 SEL>>> Да и модули ядра, я всегда считал, надо собирать "штатным"
 SEL>>> компилятором. Hо сейчас у меня стали возникать сомнения на
 SEL>>> счёт некоторых "штатных" компиляторов.
 VN>> Так известно же, что каждый подъём проверяемой версии gcc при
 VN>> сборке linux приводит к массе правок багов как в linux, так и в
 VN>> gcc.:) С остальными аналогично.
SEL> Ошибки правят, а UB напротив, холят и лелеют. Подозреваю, что ошибку
SEL> оптимизации встроенного realloc() в clang уже рапортовали, но
SEL> разбираться не стали, просто объявили UB.

Hе думаю, что они могут просто так сказать "UB, и давай досвиданья".


--netch--
--- ifmail v.2.15dev5.4
 * Origin: Dark side of coredump (2:5020/400)

(При выкладывании здесь заменил rsdn.ru на rsdn.org.)

Смотря на более поздние языки (от Java и вплоть до Go, Rust и прочих) - там все описанные проблемы „урезают“ - видимо, считают неподъёмным основной массе?

Profile

netch80: (Default)
netch80

April 2017

S M T W T F S
      1
234 5678
9101112131415
1617 181920 2122
23242526272829
30      

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jun. 27th, 2017 10:35 am
Powered by Dreamwidth Studios