LINUX.ORG.RU

4 вопроса про C++ UB

 


2

3

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

1. вот тут говорят что в С++ некое UB. если стандарт не определяет поведение для какого-то случая, то он явно это делает? т.е. там сказано типа «when X then Y must happens, in any other case - UB»? или же UB — это просто всё то, что не покрыто стандартом («а вот об этом там ничего не сказано»)?

2. регламентирует ли стандарт scope UB? или как это сказать, рамки последствий от инструкций, результат которых не определен? к примеру, в программе используется конструкция с UB, в результате чего обнулилась совсем не относящаяся к вопросу память и арифметика стала работать неправильно и т.д. гипотетический компилятор, который такую программу скомпилировал - он формально соответствовал Стандарту С++ ? или же стандарт строго очерчивает область в которой могут наблюдаться произвольный эффект?

3. что сам стандарт говорит о компилиуемости кода с неопределенным поведением? предписывает ли стандарт компилятору (претендующему на полное соответствие стандарту) отвергать код, последствия которого (даже если они имеют строго очерченные рамки) не определены стандартом?

4. возможно ли теоретически построить такой компилятор, который бы допускал инструкции с UB, но гарантировал бы отсутствие вреда от них через пресечение использования их результатов. пример: в точке A вы пишете конструкцию с у которой часть эффекта определена, а часть - UB, и всё работает нормально. но где-то далее вы добавили код (точка B) для определения результата которого необходимо использовать ранее полученный эффект из A (который UB). и вот уже такую компилятор отвергает сразу (либо останавливает ее в рантайме). ведутся ли такие разработки?

UB - неоднозначная аббревиатура. есть undefined behaviour, а есть unspecified behaviour. в первом случае стандарт не даёт гарантий на результат выполнения, во втором - стандарт не даёт гарантий, но какие-то гарантии могут быть предоставлены конкретной реализацией компилятора

urquan
()
Последнее исправление: urquan (всего исправлений: 1)
Ответ на: комментарий от urquan

В контексте C++ интересно только UB как undefined behaviour. Другое нет смысла обсуждать и вводить путающую аббревиатуру.

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)

Любое поведение программы, содержащей конструкции, приводящие к undefined behavior, будет соответствовать стандарту.

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

red75prim ★★★
()
Последнее исправление: red75prim (всего исправлений: 2)

но из любопытства возникли вопросы

Надо понимать, что спекуляция на тему UB - это всё блажь.

Человеку далекому от C++ простительно, А нормальный плюсовик знает, что присутствие понятия UB в С++ - это следствие принципа «нулевой стоимости» (zero-overhead) в языке.

Нет никакого резона философствовать на тему UB, а надо на практике почувствовать, что это такое.

int foo(int x) {
    return x+1 > x;
}

компилятор вправе для данной функции foo генерировать код, эквивалентный

int foo(int) {
    return true;
}

Т.к. «x+1 > x» для любых X, но только до момента переполнения типа int. А после переполнения наступает UB. Компилятор использует его в свою пользу (и, на самом деле, на пользу программиста!).

Именно zero-overhead не позволяет добавлять под капот проверку переполнения и кидать исключение. Программист должен сам избегать UB, контроллирую корректность данных, при этом он имеет неограниченный простор для оптимизации

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

интересно

UB - неоднозначная аббревиатура. есть undefined behaviour, а есть unspecified

я сам не уверен, что имел в виду использовав слова определять/определен. define наверное. т.е. заявить о _существовании_ конструкции и тут же связать ее с ее смыслом, а значит и тем, к чему она приводит. define

про unspecified понял, что если же поведение задано, но с допущением вариабельность в конкретном аспекте (ну или деталей того, _как_ это должно бысть сделано). я и это видимо тоже имел ввиду. (сейчас внезапно вспомнил, что лет 10 назад в институте еще написал лабу в которой аргументы порэвалюировались на VS в другом порядке чем на gcc) это видимо «unspecified» было.

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

отформатирует диск

когда писал вопрос как раз об этом примере думал.

но почему в условие соответствия стандарту не включен отказ от компиляции текстов с undefined bеhaviour ?

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

1. В стандарте явно пишут что такое UB.

Примеры:

If, within a translation unit, the same identifier appears with both internal and external
linkage, the behavior is undefined.

The lifetime of an object is the portion of program execution during which storage is
guaranteed to be reserved for it. An object exists, has a constant address, and retains
its last-stored value throughout its lifetime. If an object is referred to outside of its
lifetime, the behavior is undefined.
fsb4000 ★★★★★
()
Последнее исправление: fsb4000 (всего исправлений: 2)
Ответ на: комментарий от thomasbug

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

Так что решать неразрешимую задачу приходится программисту (шутка).

red75prim ★★★
()
Последнее исправление: red75prim (всего исправлений: 2)
Ответ на: комментарий от red75prim

не может доказать, что UB возникнет или не возникнет
If an object is referred to outside of its lifetime, the behavior is undefined.

ага, это выяснится в рантайме и уже как бы поздно.

теперь начало проясняться

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

На самом деле в 2018 году проблем с UB почти нет.

Достаточно:

1) Писать unit тесты

2) Компилировать эти тесты с флагом: -fsanitize=undefined (поддерживается и gcc и clang)

лучше даже такие флаги использовать, чтобы не только UB ловить:

-fsanitize=address -fsanitize=undefined -fsanitize=leak -fno-omit-frame-pointer

Тогда тесты будут падать если попадут на код с UB.

Написал почти, потому что возможно в компиляторах есть баги и они пока не все случаи UB ловят, но с каждой новой версией ситуация будет ещё лучше

fsb4000 ★★★★★
()

1. вот тут говорят что в С++ некое UB. если стандарт не определяет поведение для какого-то случая, то он явно это делает?

да, все такие ситуации оговорены в стандарте.

2. регламентирует ли стандарт scope UB? или как это сказать, рамки последствий от инструкций, результат которых не определен?

да, стандарт си (в стандарт си++ сейчас лень лезть, но уверен, что там то же самое) чётко оговаривает 3 возможных действия при неопределённом поведении:

  1. проигнорировать неопределённое поведение
  2. описать реакцию на такое поведение в документации и действовать в соответствии с ней
  3. прервать компиляцию или выполнение с выводом диагностических сообщений

Но это в теории. На практике, к сожалению, разработчики компиляторов интерпретируют п. 1 как «можно всё, в т. ч. отформатировать диск без всяких предупреждений в документации и/или в выводе ошибок/предупреждений компилятора». Поэтому на практике может быть всё, что угодно.

3. что сам стандарт говорит о компилиуемости кода с неопределенным поведением? предписывает ли стандарт компилятору (претендующему на полное соответствие стандарту) отвергать код

разрешает, но не предписывает.

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

теоретически возможно всё.

P.S. На самом деле неопределённое поведение нужно для того, чтобы на разных программно-аппаратных платформах код выполнялся так, как там положено. Например, в защищённом режиме обращение к 0 указателю должно приводить к аварийному завершению программы, а в реальном — к чтению/модификации 0-ого вектора прерываний. Ну и для более эффективных оптимизаций, как тут уже говорили. Однако на практике компиляторописатели трактуют свободы, данные им стандартом в случае неопределённого поведения, слишком широко, что не раз вызывало возмущение многих не последних в мире it людей, например Линуса Торвальдса.

Подробнее об этом см. мой пост О неопределённом поведении и багах оптимизатора clang на примере разбора цикла статей Криса Латтнера, разработчика clang. Там всё очень длинно, но зато подробно. Ну и можно каменты почитать, чтоб ознакомиться с разными точками зрения на этот вопрос.

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

1. проигнорировать неопределённое поведение

И как можно проигнорировать UB, и одновременно позаботиться, чтобы в случае UB ничего страшного не произошло?

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

Т.к. «x+1 > x» для любых X, но только до момента переполнения типа int. А после переполнения наступает UB.

как хитро.

zero-overhead

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

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

философствовать на тему UB, а надо на практике

нет, я не потяну с++)

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

1. проигнорировать неопределённое поведение

И как можно проигнорировать UB, и одновременно позаботиться, чтобы в случае UB ничего страшного не произошло?

А я не говорил, что стандарт предписывает, чтобы они об этом заботились. Но всё-таки «проигнорировать» — это не то же самое, что «отформатировать диск». Впрочем, не буду разводить холивар. Своё мнение я уже подробно высказал в теме, на которую кинул ссылку, и там же прочитал наверно все возможные альтернативные мнения.

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

описать реакцию на такое поведение в документации и действовать в соответствии с ней

это implementation-defined behavior. А UB может вызвать кучу разных реакций, в завивимости от применяемых оптимизаций

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

да, стандарт ... чётко оговаривает 3 возможных действия при неопределённом поведении

вот оно что

да, все такие ситуации оговорены в стандарте
нужно для того, чтобы на разных программно-аппаратных платформах код выполнялся так, как там положено

спасибо за развернутый ответ

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

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

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

описать реакцию на такое поведение в документации и действовать в соответствии с ней

это implementation-defined behavior. А UB может вызвать кучу разных реакций, в завивимости от применяемых оптимизаций

Читаем стандарт си по адресу http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf :

3.4.3

1 undefined behavior

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

2 NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

3 EXAMPLE An example of undefined behavior is the behavior on integer overflow.

Особенно внимательно вчитываемся в выделенное мною жирным начертанием.

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

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

Не всегда:

undefined behavior

behavior for which this document imposes no requirements

Note: Undefined behavior may be expected when this document omits any explicit definition of behavior ...

Т.е. если стандарт что-то недоопределил, то там тоже UB.

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

behavior for which this document imposes no requirements

Т.е. если стандарт что-то недоопределил, то там тоже UB.

Интересная трактовка. Я понимал это так, что сами ситуации определены в стандарте, а вот требований к ним со стороны стандарта нет. Но, может быть, допустимо и такое понимание.

ТС: если такое понимание допустимо (в чём я не уверен, но не уверен и в обратном, тут лучше у юристов спрашивать, они в трактовках подобных формулировок поднаторели), то мой ответ на 1-й вопрос:

да, все такие ситуации оговорены в стандарте

неверен, и правильным ответом будет:

может оговаривать явно, а может — и неявно.

aureliano15 ★★
()

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

anonymous
()

1. Да

2. Да

3. Да

4. Да

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

На самом деле в 2018 году проблем с UB почти нет.

Главное верить.

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

-fsanitize=undefined

Оно мало что ловит

Ещё один повод обновлять версии компилятора с выходом каждого нового релиза.

fsb4000 ★★★★★
()

Компиляторы часто оптимизируют, исходя из предположения, что ситуация с UB наступить не может. Переполнение int - UB, для компилятора наступить не может, и он может удалить код пользовательской проверки на переполнение. Выход за границы массива - UB, и при оптимизации лишних чтений/записей компилятор может не обращать внимания, что переменная Y может быть изменена косвенно при выходе за границы массива X. Даже если выход гарантирован, и это ясно при компиляции.

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

Для указание на возможность косвенного изменения Y есть volatile.

bormant ★★★★★
()

4. Возможно. В данный момент разрабатываются компилятор (не для c++) в котором присутствует такая возможность, но есть ограничения.

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

Y может быть изменена косвенно при выходе за границы массива X.

Ну это уже даже не косвенно.

Косвенно, это когда у вас RO регистр, который меняется аппаратно (ну или, покрайней мере, не вашей программой).

А при выходе за границы массива она меняется очень даже напрямую.

RiseOfDeath ★★★★
()

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

Но зачем? Надо разграничивать UB по стандарту и UB на платформах. Очень часто это UB имеет вполне себе определенное поведение на конкретной аппратной/софтверной платформе. И это можно использовать для оптимизаций. Да, такой код не соответствует стандарту, что означает лишь, что его работа не гарантирована на другой платформе и компиляторе, которые отвечают стандарту. Но такой код может вполне себе удовлетворять ТЗ проекта. В общем это бессмысленно и никому не нужно.

Если хочется избегать UB, то надо компилить проект с включеным оповещением о ВСЕХ варнингов. И прогонять код через статические анализаторы.

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

P.S. На самом деле неопределённое поведение нужно для того, чтобы на разных программно-аппаратных платформах код выполнялся так, как там положено. Например, в защищённом режиме обращение к 0 указателю должно приводить к аварийному завершению программы, а в реальном — к чтению/модификации 0-ого вектора прерываний. Ну и для более эффективных оптимизаций, как тут уже говорили. Однако на практике компиляторописатели трактуют свободы, данные им стандартом в случае неопределённого поведения, слишком широко, что не раз вызывало возмущение многих не последних в мире it людей, например Линуса Торвальдса.

Для того, чтобы на разных программно-аппаратных платформах код выполнялся так, как там положено, существует implementation defined или unspecified behaviour. Это позволяет, например, оператору сдвига вправо от знаковых чисел превращаться в ту инструкцию, которая есть на требуемом процессоре, и надеяться, что программист, которому важно поведение при отрицательных числах почитает инструкцию к своему компилятору. Это же позволяет ему вычислять аргументы функции в любом порядке, чтобы они клались на стек, как того требует соглашение о вызовах (хотя сомневаюсь, что хотя бы один современный компилятор руководствуется именно этим соображением).

Разыменование нулевого указателя в си/си++ и машинная инструкция, пишущая что-то по адресу [0] — это абсолютно разные и в общем случае не связанные друг с другом вещи. Некоторые компиляторы могут задокументировать, что они всегда превращают первое во второе, другие могут делать это для указателей, помеченных специальным атрибутом, а третьи будут считать эту ситуацию недопустимой, обрубать все пути исполнения, ведущие к такому результату и требовать от «системщиков» ассемблерных вставок в тех случаях, когда они хотят определённых машинных инструкций.

К сожалению, большое количество ЛОРовцев и просто программистов считают, что задача компилятора — это пройтись по всем строчкам программы, сгенерировать соответствующие каждой строчке машинные инструкции и может быть что-то попереставлять, чтобы выполнялось быстро. Особо упёртые ещё считают, что компилятор после этого находит места, где есть UB, и вставляет туда всякие гадости.

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

Как правильно выше заметили, для борьбы с собой можно использовать ворнинги компилятора, *san и тесты, и постоянно практиковаться, напарываясь на очередные грабли. Через пару-тройку лет все грабли станут до милости знакомыми и понятными.

Ещё можно ввести некоторые правила программирования: например, вместо int использовать собственный класс Int, который имеет конструктор по умолчанию, проверяет правильность всех арифметических операций, вместо массивов и указателей использовать указатели, сохраняющие информацию о допустимых границах обращения и считающие ссылки, вместо магии над атомарными переменными использовать доступы, надёжно защищённые двумя мьютексами. Но можно просто взять другой язык программирования, типа питона, в котором всё это есть из коробки.

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

P.S. Я согласен, что исторически UB могло появиться как разновидность платформозависимого поведения (и могло читаться как «будет машинное исключение»), но с 90х годов многое изменилось.

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

Ещё можно ввести некоторые правила программирования: например, вместо int использовать собственный класс Int, который имеет конструктор по умолчанию, проверяет правильность всех арифметических операций, вместо массивов и указателей использовать указатели, сохраняющие информацию о допустимых границах обращения и считающие ссылки, вместо магии над атомарными переменными использовать доступы, надёжно защищённые двумя мьютексами. Но можно просто взять другой язык программирования, типа питона, в котором всё это есть из коробки.

Золотые слова! Полностью поддерживаю. Зачем нужен сложный си, когда есть не менее эффективные, но гораздо более простые ява и питон? Уверен, что операционные системы пока что пишут на си только по привычке. Но скоро разработчики ОС поймут, что питон для этих целей не только проще, но и эффективнее, хотя бы потому, что банальное создание целочисленной переменной не приводит там к вызову громоздкого конструктора, а потом и деструктора. Так что через пару лет мы увидим первую ось, написанную на питоне, а лет через десять вообще все системы, драйвера и прошивки будут писать исключительно на питоне, бейсике, яве и шарпе, а си с плюсами и без них умрёт за ненадобностью. Слава создателям стандарта и компиляторописателям! Они медленно, но верно подводят нас к этому золотому веку. А я-то, наивный человек, ещё удивляюсь, отчего это в наше время программы на 8 гигах и 4 многогигагерцных ядрах тормозят сильнее, чем в 90-е тормозили точно такие же программы с таким же функционалом на 8 метрах и 1 стомегагерцном ядре. В общем, прощай, си, пошёл изучать питон — системный язык будущего!

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

Если хочется избегать UB, то надо компилить проект с включеным оповещением о ВСЕХ варнингов. И прогонять код через статические анализаторы.

UB не определяется статически в 100% случаях, так что ubsan, дизасм, молитва и пост.

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

Поэтому на исходную последовательность действий компилятору плевать, его задача — сгенерировать оптимальный на его взгляд код, приводящий с точки зрения стандарта к тому же результату.

Ты перепутал причину и следствие. Компилятору именно насрать на результат и работает он с последовательностью, либо с отдельными паттернами/инструкциями. В основном все оптимизации сводятся к свёртке констант и инлайнингу, а всё остальное - полурабочий колхоз, который каждый ваяет как хочет.

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

В конечном итоге мы имеем поломанное всё, при этом профит от подобного очень сомнителен, а проблем это вызывает много. Наоборот - профит от этого отрицательный.

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

Это опять же подмена причины и следствия. Подобные процессоры не следствие чего-то полезного, а следствие деградации. Эта ветвь - тупиковая ветвь и рано или поздно она умрёт. Spectre - очередной гвоздь в крышку этого гроба.

Все подобные решения - это следствие легаси и только его. Нельзя просто так ввести на рынок новую архитектуру, нельзя просто так ввести на рынок нормальный компилятор. В мире есть фундаментальная проблема - маздай и от этого никуда не уйти.

Именно поэтому мы и имеем самую ущербанскую архитектуру, которую интел уже давно бы выкинул, но он не может. Уже давно интел в большинстве случаев упирается во фронтенд, а это прямое следствие ущербанской архитектуры. Именно в это упирается и суперскалярность.

Оказалось, что проще написать умный компилятор и собрать умный процессор

Когда ты вендор процессора и компилятора, то да. Ты опять всё перепутал. Вендор процессоров не может влиять на колхозников.

И ты сам себе противоречишь. Умному процессору не нужен компилятор - он на то и умный, что делает за компилятор его работу. Когда у тебя будет умный компилятор - 95% умного процессора можно выкинуть.

Но даже умный процессор дерьмо и не может без компилятора, именно поэтому интелу и проходится ваять компилятор и тысячи блобов. Ведь развитие суперскалярности уже давно почти прекратилось. И без блобов колхозник просто не увидит разницы между корой2 и последней микроархитектурой.

И точно так же, как умный процессор упёрся в стену - в неё упёрся и компилятор. Ведь компилятор не даёт ничего в макро-масштабах. Именно поэтому детсадовцы с пистоном нихрена не могут, кроме лабы.

И именно поэтому пистон на 95% и состоит из сишных блобов. И именно поэтому у пистона и нет никакого компилятора, а есть мусорные поделки. И так всегда было, есть и будет.

Даже для микро-оптимизаций, которые и делает компилятор - нужны предпосылки. Нужна свобода. Именно эту свободу и даёт нормальный язык и нормальный программист. И этого ты никогда не изменишь.

двумя мьютексами.

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

Именно поэтому колхозник не понимает ни современной микро-арихтектуры, ни вообще чего-то сложнее 386. И это и есть проблема.

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

К сожалению, большое количество ЛОРовцев и просто программистов считают, что задача компилятора — это пройтись по всем строчкам программы, сгенерировать соответствующие каждой строчке машинные инструкции и может быть что-то попереставлять, чтобы выполнялось быстро. Особо упёртые ещё считают, что компилятор после этого находит места, где есть UB, и вставляет туда всякие гадости.

Неверно. Большое кол-во лоровцев никакого отношения к С/С++ не имеют и ничего вообще( в данной теме) не считают.

Именно так и работает компилятор, а то, что ты описываешь - это маня-фантазии. Компилятор имеет поток инструкций, точно так же как и процессор. Ничего с ним он сделать не может, ничего о них он не знает. Какой результат они дадут - он не знает. Этого ничто не изменит.

И мало того, ты даже пишешь ахинею. «сгенерировать соответствующие каждой строчке машинные инструкции» - какие, нахрен, машинные инструкции в си? Чему именно они должны соответствовать? Ты хотел сказать «соответствующие каждой языковой конструкции» - да, именно это и нужно от компилятора. Но если ты правильно это сформулируешь - твои инсинуации на тему тут же развалятся.

А у каждой языковой конструкции есть результат и нужен именно этот результат. И именно этот результат и не должен изменять компилятор. И если там будет УБ - код должен работать так, как написано. Наличие там УБ не отменяет этого правила.

И, как я уже говорил, компилятор намеренно портит код с УБ и это факт.

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

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

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

Ну и в посте наглое 4.2 — или покажи мне современную программу и ещё аналог с абсолютно таким же видом и функционалом из 90х, различающиеся только потреблением ресурсов.

P.S. Если уметь готовить джаву, то на типичных «бизнес» задачах типа строчку перекинуть туда-сюда (подождав её по сети пару секунд) и хтмл-страничку отрендерить она работает не сильно медленнее плюсов, но шансов попортить память соседнему объекту там нет. За то время, пока средненький плюсовик отдебажит свои сегфолты, средненький джавист уже закончит два таких проекта.

vzzo ★★★
()
Последнее исправление: vzzo (всего исправлений: 1)
Ответ на: комментарий от vcerloman

Особо упёртые ещё считают, что компилятор после этого находит места, где есть UB, и вставляет туда всякие гадости.

И, как я уже говорил, компилятор намеренно портит код с УБ и это факт.

Что и требовалось доказать :-)

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

На это потуги заканчиваются, как и аргументация? Очередные глупые потуги малограмотных трепачей - ничего нового.

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

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

Уважаемое трепло, а ты не знал о том, что твой пистон такая же си-лапша? А ты не знал, что любая скриптуха - есть лишь интерфейс на сишной лапшой, который с таким же уровнем безопасности используется и в тех же крестах.

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

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

Очередные эксперты в треде. Ты там уже написал хоть что-то на расте, либо очередная балаболка, которая ретранслирует поверья из интернета?

P.S. Если уметь готовить джаву, то на типичных «бизнес» задачах типа строчку перекинуть туда-сюда (подождав её по сети пару секунд) и хтмл-страничку отрендерить она работает не сильно медленнее плюсов, но шансов попортить память соседнему объекту там нет. За то время, пока средненький плюсовик отдебажит свои сегфолты, средненький джавист уже закончит два таких проекта.

Очередная ахинея от домохозяйки. Мы тут видим типичную подмену понятий. Плюсовик будет гонять хтмл-стринички с таким же успехом и за то же время, даже за меньшее. В крестах намного шире возможности по построению удобных интерфейсов.

Никаких сегфолтов в крестовом коде быть не может. За 5минут прикручивается ГЦ и их вообще никогда не будет.

Ах ну да, я не рассказал пацанам о том, что именно балабол подменяет. Всё дело в том, что жавист пишет хелворд-дерьмо по перекидыванию хмл"чика по сети. Подавляющие большинство крестовиков не пишет хелворды - они пишут рантайм, т.е. либы, либо какие-то унифицированные решения. На крестах никто не клепает конвейерный веб.

Т.е. потуга из разряда «вот мои фокусы штампуют сотнями в час, а в ваших говяных астон-мартинах ловят неделю сегфолты» - они попросту несостоятельна.

Любую либу для вебчика жабисты пишут 10лет и точно так же 10лет её отлаживают. На подобных нюансах колхозники часто ловятся.

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

Да в этом потоке сознания просто не на что отвечать — вся аргументация есть в моём первом посте, а твой ответ на него — это несодержательные придирки к тексту (типа того, что вместо «строчка» надо было написать «языковая конструкция», и тогда что-то бы изменилось), попытки выдёргивать из контекста (типа пассажа о том, то процессор «умным» собирается из-за легаси, хотя это именно то, что написано в моём посте) и какие-то не имеющие отношения к действительности заявления, преподносящиеся как очевидные истины (типа «все оптимизации сводятся к свёртке констант и инлайнингу», «компилятор имеет поток инструкций, ничего с ним он сделать не может, ничего о них он не знает» и «компилятор не даёт ничего в макро-масштабах»).

Почитай что-нибудь про компиляторы посовременнее драконокниги (типа исходников или хотя бы доков LLVM/Clang). Если читать сложно, то это есть на ютюбе с картинками со всяких сипипиконов. Начать можешь с разбора самого заезженного примера оптимизации, не оставляющей ни одной инструкции, соотвествующей изначальным «языковым конструкциями»: https://godbolt.org/g/7A44Dz. Дальше можешь почитать про PGO, LTO, хотя бы TBAA, и вернуться в тред.

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

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

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

Остальная часть поста опять лежит в категории фантазий («Никаких сегфолтов в крестовом коде быть не может», «За 5минут прикручивается ГЦ», «Подавляющие большинство крестовиков пишут рантайм»).

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

понять, что для решения разных задач используются разные инструменты.

И опять я не спорю, а поддерживаю!

Питон — для одних задач, а си — для других. И не надо их смешивать, пытаясь создавать какие-то сложные классы Int с виртуальными функциями в си++ и ещё более сложные структуры Int с явно объявленными таблицами указателей на разные функции инициализации или чего-то там ещё в чистом си, чтоб в конечном итоге сэмулировать питон и избежать ub.

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

И не только это. Вообще из пушек по воробьям стрелять не надо. Есть ява, питон, баш и целый класс задач, для которых эти языки подходят, а си не нужен не только из-за опасности, но просто из-за чрезмерной сложности. В конце концов, если мне надо вывести из скрипта содержимое текущей директории на экран, проще написать на баш одну команду ls, чем создавать длинный цикл readdir() на си.

Но есть такие задачи, для которых нужен именно си, причём зачастую даже без плюсов. И вот его-то компиляторщики и стандартизаторщики пытаются превратить в новую яву, только гораздо более опасную и сложную и, боюсь, менее эффективную. А зачем нам 2-ая ява, да ещё и заведомо худшая, чем та, которая уже есть?

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

Ну и в посте наглое 4.2 — или покажи мне современную программу и ещё аналог с абсолютно таким же видом и функционалом из 90х, различающиеся только потреблением ресурсов.

В 90-е я купил крутой комп с 8 метрами памяти только потому, что мне нужна была прожорливая 3d-studio ещё под DOS'ом. Для остального такие объёмы были не нужны. С тех пор я не работал с кадами. Сколько сейчас нужно памяти для той же 3D Studio или чего-то аналогичного? 32 метров хватит или надо разориться на 64 метра?

Тогда же был браузер Netscape Navigator, дедушка Firefox'а, на 8 метрах летал. А ещё был Spyglass Mosaic — этот вообще на чём угодно летал. А как сейчас обстоят дела? Мне хватит 16 метров на современный графический браузер или лучше поставить 32 метра на всякий пожарный?

Помню ещё IDE Delphi и C++ Builder. Они тоже летали на этой памяти, как и программы, которые они генерили. А сейчас как обстоят дела? Для Qt Creator 5 сколько нужно памяти? Ну уж 16-ти-то метров должно хватить для комфортной работы? А сколько памяти будут потреблять графические приложения, собранные на Qt?

А вот когда появилась Windows XP — ты не поверишь, какая это была прожорливая система! На 8 метрах она вообще не запускалась, на 16 метрах запускалась с трудом и дико тормозила, и только на 32 метрах с ней можно было комфортно работать. Но уж теперь-то дела обстоят иначе, ведь прогресс не стоит на месте, и современные графические оболочки летают и на 4 метрах, как Windows 3.11. Или нет?

Да, ты спросишь, что это я всё про Windows и про Windows на Linux-форуме? Ну извини, в то время был виндузятником, поэтому про Линукс тех времён мне вспомнить нечего. Но уверен, если бы было чего, то и там дела в плане потребления ресурсов обстояли не хуже, а возможно лучше, чем в Windows.

P.S. Если уметь готовить джаву, то на типичных «бизнес» задачах типа строчку перекинуть туда-сюда (подождав её по сети пару секунд) и хтмл-страничку отрендерить она работает не сильно медленнее плюсов

Ну если только перекинуть туда-сюда. И не на метр дальше.

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

Как я понимаю, ты можешь только трепаться, да? Ты мне рассказываешь о том, что я к чему-то придирался, что-то дёргал, но почему же ты мне не показываешь что? Покажи мне. Почему все все такие одинаковые. Каждый тебе расскажет о том, что ты что-то там сделал, но никто не покажет где и как. Действуй.

Почитай что-нибудь про компиляторы посовременнее драконокниги (типа исходников или хотя бы доков LLVM/Clang).

Уважаемый колхозник, я не читаю дерьмо и меня оно не волнует. Мнение домохозяек о том, что мне нужно, либо не нужно читать - меня не волнуют. Есть что возразить по существу - возражай, а ахинею мне не неси. Подобное будешь вещать соседям по парте.

Начать можешь с разбора самого заезженного примера оптимизации, не оставляющей ни одной инструкции, соотвествующей изначальным «языковым конструкциями»:

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

Что мы тут видим, тут балабол пытается врать, приписывая мне «компилятор должен генерировать код соответствующий каждой языковой конструкции», пытаясь опровергать мои слова тем, что компилятор на самом деле их меняет. И должен менять.

Но, специально для идиотов я написал дополнение, в котором присёк подобные потуги, а именно:

А у каждой языковой конструкции есть результат и нужен именно этот результат. И именно этот результат и не должен изменять компилятор.

Т.е. я говорил о том, что не должен меняться результат, а трепло говорит о чём? «не оставляющей ни одной инструкции».

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

Дальше можешь почитать про PGO, LTO, хотя бы TBAA, и вернуться в тред.

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

Во-первых lto никакого отношения к оптимизации вообще не имеет. Колхозник опять всё перепутал. Из этого следует очень простой вывод - колхозник пастил рандомные базворды.

Как именно и в чём PGO и AA меня должны опровергнуть? Что из это следует?

https://godbolt.org/g/7A44Dz.

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

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

Так используй интерфейсы и не используй ненужные фичи вместо того чтобы ныть,

Уважаемый балабол. Используешь интерфейсы и жрёшь то дерьмо, которым тебя кормят - ты, а не я. Твои потуги и твои рассуждения - меня не волнуют, и волновать не должны.

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

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

При правильно написанном интерпретаторе или виртуальной машине нельзя вызвать плюсовое UB

Это никого не волнует. УБ требует возможностей, которых нет в недоязычках. Если ты сравниваешь кресты и недоязычки, то ты должен ограничить кресты.

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

а следствие того, что программисты интерпретаторов и виртуальных машин живут в объективной реальности и понимают, что у плюсового UB не может быть никакого ожидаемого поведения в принципе

Если это уровень пистона - да, но они попросту не обладают необходимой квалификацией, как и ты. Те, кто ею обладают - понимают.

И да, почему-то ты противоречишь авторам компиляторов, которые трактуют УБ как ожидаемое поведение? «не работает», «не ожидаемое» - это ожидаемое поведение. Это определённое поведение.

Давай я тебя научу в логику. УБ предполагает любое поведение, а любое - это не значит «не работает», это не значит «неожидаемое».

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

Остальная часть поста опять лежит в категории фантазий («Никаких сегфолтов в крестовом коде быть не может», «За 5минут прикручивается ГЦ», «Подавляющие большинство крестовиков пишут рантайм»).

Так и запишем - обделался, в очередной раз.

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

Питон — для одних задач, а си — для других.

Неверно. Никакой пистон несостоятелен за рамками лабы, а в контексте С/С++ совсем. Не существует никаких «языков под задачи» - это всё маня-мирок колхозников. Дай этому колхознику голый язык и он обделается, ведь он трепло.

Все эти рассуждения про области базируются на наличии готового дерьма, либо каким-то вендор-локом. Иного не дано. Т.е. «нужный язык» в рамках «нужной области» становиться очередным башем, который состоятелен только потому, что кто-то уже реализовал для домохозяйки апи, которым она может играться с вебом.

И разница между колхоз-языком и С++ лишь в том, что этот язык намного сложнее любого недоязычка и колхозники просто не могут на нём писать. Пусть даже там будет абсолютно такой же набор либ с идентичным апи.

Именно поэтому С/С++ и недоязычки находятся в разных нишах. На С/С++ пишут код, а на недоязычках скриптуху, т.е. некий текст, который будет оттранслирован в набор сишной логики, либо готовой логики на недоязычке.

А когда нам не нужно писать код, то зачем нам полноценный язык? Нам подойдёт дерьмо уровня «бэ-мэ» для дошколят, которое мы и назовём языком. И пусть на нём ничего, кроме скрипту и лабы не напишешь, но зачем - напишут другие, а мы будем рассказывать как у нас всё круто.

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

Питон — для одних задач, а си — для других.

И пусть на нём ничего, кроме скрипту

Ну, если для решения задачи достаточно однострочного скрипта, то зачем городить си-огород? Просто чтоб из пушки по воробьям стрельнуть?

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

Понимаешь в чём штука - это фундаментальная дыра в представлении о реальности. Когда ты однострочник на скриптухе - ты не пишешь код на языке, ты лишь комбинируешь некие вызовы api и гоняешь данные между ними. И ошибка тут в том, что это api зашито в язык и выглядит как язык, но это не язык.

Простой тому пример bash и coreutils. Является ли использование grep какой-то конструкций языка? Нет. Просто bash тебе даёт api по управлению stdout/in. И «проще» это писать на баше лишь потому, что в одном случае у тебя есть готовое api, а в другом нет.

Но ничего не мешает его добавить, а не добавляют его по той причине, что на си нет смысла заниматься подобным - на нём пишут coreutils.

Т.е. наличие какого-то api не следствие языка, это не заслуга языка. Ты там рассказывал про маздай, дак вот - маздайские powershell - это типичная реализация подобного интерфейса на «не скриптовом» языке.

Ты можешь реализовать и получить идентичное api на тех же крестах и тебе ничего не помешает.

Просто чтоб из пушки по воробьям стрельнуть?

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

Не сравнивай язык и не язык.

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