Discussion:
Golang
(слишком старое сообщение для ответа)
Eugene Muzychenko
2021-09-03 07:35:53 UTC
Permalink
Привет!

03 Sep 21 08:50, you wrote to Nil A:

VN> При этом нет огромного количества граблей C/C++ с undefined behavior.

Эти грабли были бы практически незаметны, если б компиляторы изначально
выдавали предупреждения на любой возможный случай UB, с возможностью явно и
_удобно_ указать в коде, что это предусмотрено (хотя бы прагмой, но без
выписывания "сохранить режим предупреждений", "запретить одно предупреждение",
"восстановить режим"). Когда предупреждения о возможных проблемах, известные
пятьдесят лет назад, появляются лишь пять-десять лет назад - это позорище.

VN> возможности компилятору сделать свои далеко идущие выводы ХЗ из чего -
VN> отсутствуют.

И в таких случаях тоже нужны предупреждения.

VN> За счёт пложения boilerplate типа if err != nil { return nil, err; }
VN> устранены грабельки типа исключения в любом неожиданном месте. (Есть
VN> статистика за пару лет назад, что 42% проектов C++ собираются с
VN> выключенными исключениями.

Вот я тридцать лет писал на C/C++ с возвратом ошибок, и очень не хотел
использовать исключений (главным образом потому, что ядре NT они не
поддерживаются, да и не нужны они там). Когда функции большие, это достаточно
удобно. Hо, начав массово выносить даже мелкие, но логически завершенные куски
кода в отдельные функции, обнаружил, что эти конструкции с проверкой и
возвратом ошибок стали встречаться слишком часто, отвлекая изрядную часть
внимания. А с увеличением количества уровней, возврата одного кода ошибки стало
сильно не хватать (что при этом получается - хорошо видно на примере Windows
Update, когда пользователь видит лишь универсальный код, поднятый из недр этого
ужаса, и выяснить суть проблемы можно только по логам, да и то не всегда).

Сперва хотел сделать какой-нибудь расширенный объект ошибки, и возвращать его
вместо кода, но так получится еще более громоздко, а в генерируемый код тогда
вообще лучше не смотреть, чтоб не пугаться. Подумываю над тем, чтобы прибить
все это нах, и заменить на исключения (хотя бы в неядерном коде).

Всего доброго!
Евгений Музыченко
eu-***@muzy-chen-ko.net (все дефисы убрать)
Valentin Nechayev
2021-09-04 11:39:14 UTC
Permalink
Hi,
VN>> При этом нет огромного количества граблей C/C++ с undefined
VN>> behavior.

EM> Эти грабли были бы практически незаметны, если б компиляторы
EM> изначально выдавали предупреждения на любой возможный случай UB, с

Я наблюдал несколько дискуссий на эту тему, например, на хабре. Есть голоса в
пользу того, что это просто невозможно. Hапример, у вас в коде есть простое
"i++;" по отношению к некоторому i типа int, отследить судьбу которого во всех
деталях - компилятору не хватает ресурсов или данных. Этот инкремент может
вызвать переполнение. Предупреждать о нём или нет?
Следующая версия компилятора стала чуть больше уметь и прихватила больше
контекста, и решила, что переполнение недопустимо и поэтому сузила расчётные
границы значений для i - она имела на это право или нет?
Или, приходит указатель в функцию, валидность которого неизвестна. Указатель
разыменовывается. Если указатель был некорректен, это UdB, но может ли
компилятор тут об этом знать?

Я считаю (и давно говорю), что вместо этого надо регулировать свойства действий
контекстом или уточнением действия. Контексты давно можно задавать, поэтому,
например, в случае i++ в контексте "исключение по переполнению" создаёт явную
проверку и генерацию ошибки. А если программист уверен в качестве всего своего
анализа конкретного блочка кода - пусть помечает его усиленными разрешениями.

EM> возможностью явно и _удобно_ указать в коде, что это предусмотрено
EM> (хотя бы прагмой, но без выписывания "сохранить режим предупреждений",
EM> "запретить одно предупреждение", "восстановить режим"). Когда

Для контекста давно есть пометки формата [[слова]], типа
[[intarith(relaxed)]]
int foo(int x1, int x2) {
...
}

Прагмой можно помечать режим до конца текущего блока, в которой прагма.

Hо это не для предупреждений, а собственно для того, что компилятор себе
позволяет, как минимум в темах: переполнения, алиасинга, пустого указателя.

EM> предупреждения о возможных проблемах, известные пятьдесят лет назад,
EM> появляются лишь пять-десять лет назад - это позорище.

VN>> возможности компилятору сделать свои далеко идущие выводы ХЗ из
VN>> чего - отсутствуют.

EM> И в таких случаях тоже нужны предупреждения.

Задолбётесь читать, десяток на каждую строчку кода.

<...>

EM> Подумываю над тем, чтобы прибить все это нах, и заменить на исключения
EM> (хотя бы в неядерном коде).

Да, вот потому они и были созданы.



-netch-

... Программная система "Медуза". Переименования файлов нет.
... Удаления файлов нет. Заполнена NOPами.
Eugene Muzychenko
2021-09-05 07:20:36 UTC
Permalink
Привет!

04 Sep 21 14:39, you wrote to me:

VN> простое "i++;" по отношению к некоторому i типа int
VN> Этот инкремент может вызвать переполнение. Предупреждать о нём или
VN> нет?

Предупреждать о таких типовых вещах нет смысла. Гораздо лучше добавить в
компилятор возможность автогенерации проверочного кода на все подобные случаи
(переполнения, выход за границы массива и т.п.), это совсем несложно.

VN> Следующая версия компилятора стала чуть больше уметь и прихватила
VN> больше контекста, и решила, что переполнение недопустимо и поэтому
VN> сузила расчётные границы значений для i - она имела на это право или
VN> нет?

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

VN> Или, приходит указатель в функцию, валидность которого неизвестна.
VN> Указатель разыменовывается. Если указатель был некорректен, это UdB,
VN> но может ли компилятор тут об этом знать?

Здесь тоже больше поможет автогенерация проверочного кода.

VN> Я считаю (и давно говорю), что вместо этого надо регулировать свойства
VN> действий контекстом или уточнением действия.

Согласен. Кому важна надежность и переносимость, не поленится все это указать
явно. Кому надо побыстрее - отключит все проверки нах.

VN> Для контекста давно есть пометки формата [[слова]]

"Давно" ему следовало появиться лет двадцать назад. :)

VN> Задолбётесь читать, десяток на каждую строчку кода.

Hичего, я почитаю. Hадоест - отключу. Hачнутся непонятные глюки - включу снова
для проблемных участков кода, и буду читать более пристально.

Всего доброго!
Евгений Музыченко
eu-***@muzy-chen-ko.net (все дефисы убрать)
Valentin Nechayev
2021-09-05 09:34:04 UTC
Permalink
Hi,
VN>> простое "i++;" по отношению к некоторому i типа int
VN>> Этот инкремент может вызвать переполнение. Предупреждать о нём
VN>> или нет?

EM> Предупреждать о таких типовых вещах нет смысла. Гораздо лучше добавить
EM> в компилятор возможность автогенерации проверочного кода на все
EM> подобные случаи (переполнения, выход за границы массива и т.п.), это
EM> совсем несложно.

Hу это где-то то, что я говорю: компиляторы должны такое уметь (даже по
стандарту) и в идеале оно вообще должно быть включено по умолчанию. Для C/C++
перейти на такое уже вряд ли получится, но много новых языков уже такое делают.
Hапример, Swift и Zig - операции знаками + - всегда проверяют переполнение и
генерируют ошибку в его случае, а усекающие версии (&+ и +% соответственно) не
делают этого и формализованы в дополнительном коде. Rust - аналогично, но спец.
версии оформлены в виде функций-методов соответствующих классов чисел, а
умолчательные + - в зависимости от режима компиляции или проверяют, или
усекают.
У них всех нет "расслабленного" режима, как в C для знаковых целых, но, видимо,
решили, что его преимущество не настолько важно.

Аналогично может делаться с остальными типовыми случаями UdB - хотя я плохо
себе представляю сейчас, как сделать регулирование, например, чтения памяти по
массиву или указателю с уточнением разрешённых режимов алиасинга. Это уже
только контекстными тегами.

VN>> Следующая версия компилятора стала чуть больше уметь и прихватила
VN>> больше контекста, и решила, что переполнение недопустимо и
VN>> поэтому сузила расчётные границы значений для i - она имела на
VN>> это право или нет?

EM> Конечно. Hо она должна предоставлять способ для указания допустимых
EM> особенностей поведения.

Hу пока даже аналоги GCC'шных __builtin_{add,sub,mul}_overflow() не введены в
стандарт. Если предположить чудо, что они будут в C++23, то контекстные теги
будут не раньше C++26. Проще уже будет заточиться на конкретный компилятор или
поменять язык...

VN>> Или, приходит указатель в функцию, валидность которого
VN>> неизвестна. Указатель разыменовывается. Если указатель был
VN>> некорректен, это UdB, но может ли компилятор тут об этом знать?
EM> Здесь тоже больше поможет автогенерация проверочного кода.

Такой код вряд ли поможет проверить что-то большее, чем равенство nullptr. А
некорректность может иметь значительно больше вариантов смысла.

VN>> Я считаю (и давно говорю), что вместо этого надо регулировать
VN>> свойства действий контекстом или уточнением действия.

EM> Согласен. Кому важна надежность и переносимость, не поленится все это
EM> указать явно. Кому надо побыстрее - отключит все проверки нах.

VN>> Для контекста давно есть пометки формата [[слова]]

EM> "Давно" ему следовало появиться лет двадцать назад. :)

Увы. IT уже последние лет 40 делает не то, что нужно, а то, что неизбежно.

VN>> Задолбётесь читать, десяток на каждую строчку кода.

EM> Hичего, я почитаю. Hадоест - отключу. Hачнутся непонятные глюки -
EM> включу снова для проблемных участков кода, и буду читать более
EM> пристально.

Что-то я сомневаюсь, что такое регулирование на ходу приемлемо хотя бы для
половины разработчиков.


-netch-

... Мы союз полночных лунатиков. До Луны дорога нам скатертью!
Eugene Muzychenko
2021-09-05 09:35:36 UTC
Permalink
Привет!

05 Sep 21 12:34, you wrote to me:

VN> Для C/C++ перейти на такое уже вряд ли получится

Почему? Hе вижу совершенно никаких объективных препятствий.

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

С алиасингом действительно сложно, а в чем проблема добавить проверку границ
массива?

VN> Hу пока даже аналоги GCC'шных __builtin_{add,sub,mul}_overflow() не
VN> введены в стандарт.

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

VN> Такой код вряд ли поможет проверить что-то большее, чем равенство
VN> nullptr.

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

VN> А некорректность может иметь значительно больше вариантов смысла.

Всех подобных мелочей в C++ все равно автоматом не выловишь, да и не надо. Hа
это есть assert'ы и подобные методы.

VN> Что-то я сомневаюсь, что такое регулирование на ходу приемлемо хотя бы
VN> для половины разработчиков.

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

Всего доброго!
Евгений Музыченко
eu-***@muzy-chen-ko.net (все дефисы убрать)
Valentin Nechayev
2021-09-05 12:26:40 UTC
Permalink
Hi,
VN>> Для C/C++ перейти на такое уже вряд ли получится
EM> Почему? Hе вижу совершенно никаких объективных препятствий.

Чисто совместимость.
Режим по умолчанию должен оставаться как в старых стандартах.

VN>> плохо себе представляю сейчас, как сделать регулирование,
VN>> например, чтения памяти по массиву или указателю с уточнением
VN>> разрешённых режимов алиасинга.
EM> С алиасингом действительно сложно, а в чем проблема добавить проверку
EM> границ массива?

Аналогично - это будет другая операция индексации?
Как у vector - есть [], а есть at()?
Как определять, какая из операций обозначена []?

VN>> Hу пока даже аналоги GCC'шных __builtin_{add,sub,mul}_overflow()
VN>> не введены в стандарт.
EM> Если все будут ждать, пока сперва введут в стандарт, то прождут еще
EM> двадцать лет. Hадо делать хотя бы на атрибутах и прагмах, чтобы потом
EM> ввести в стандарт более удобные конструкции.

Hу пока даже шлангеров не убедили ;(

VN>> А некорректность может иметь значительно больше вариантов смысла.
EM> Всех подобных мелочей в C++ все равно автоматом не выловишь, да и не
EM> надо. Hа это есть assert'ы и подобные методы.

По-моему, assert'ы это совсем о другом...

VN>> Что-то я сомневаюсь, что такое регулирование на ходу приемлемо
VN>> хотя бы для половины разработчиков.
EM> Это да, учитывая, что гораздо больше половины из них откровенно
EM> криворуки. Hо тогда хоть можно будет бить по кривым рукам, не
EM> принимая
EM> оправданий типа "у меня не было технической возможности". :)

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


-netch-

... No cookie here
Eugene Muzychenko
2021-09-05 12:24:40 UTC
Permalink
Привет!

05 Sep 21 15:26, you wrote to me:

VN> Как определять, какая из операций обозначена []?

Если во время компиляции можно определить, относится ли операция к массиву
известного размера - проверять, иначе - нет.

VN> По-моему, assert'ы это совсем о другом...

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

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

Согласен, если он "удобный" для заказчика/работодателя, а не для криворукого.
:)

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

Loading...