Обновить
0
0

Пользователь

Отправить сообщение
Меня не скорость записи в первую очередь интересует, а надёжность.
Что-то не похоже на SLC. Если диск изначально был TLC, а мы его хотим использовать как SLC, то по идее объём должен упасть в 3 раза. А там, в этой таблице на стр. 70, разница между максимальным и минимальным объёмом меньше, чем в 2 раза. Или производитель в «нормальном» (со своей точки зрения) TLC-режиме закладывает физический объём в полтора раза больше заявленного?
хороший tlc
Хороший — это сколько циклов перезаписи?
godbolt.org/z/85o7xhjxe
О, нет, и вы туда же. Я ещё понимаю, что этот 91-й сайт использует топикстартер, который топит за UB. Но вы-то вроде как против? И даже критикуете обновления компилятора за деградацию (с точки зрения программиста). А для примеров всё равно 91-й сайт используете.

По делу. Я так понимаю, «poison» внутри llvm-функции main — это не перенос имени переменной из исходника, а ключевое слово этого языка llvm. Но я не очень знаю особенности работы языка llvm, поэтому не очень понимаю, что будет, если этот пример дальше скомпилировать в реальный машинный код? Будет возвращаться неинициализированное значение? Или опять инструкцию ret снесут целиком, передав управление дальше по памяти (вот теперь уже точно с непредсказуемыми последствиями, поскольку функция последняя)?

(И да, в любом случае, к «близости к железу» и «использованию возможностей процессора так, как этого хочет программист» это отношения не имеет, независимо от ответа.)
Да, это тоже решение (хотя и к нему относится замечание выше об избыточной защите).
kill -11?
Хорошо, под «нормальным способом» я имел в виду «изнутри программы». Другими словами — как дать программе такой ввод, чтобы произошло чтение по нулевому адресу. Но да, для решения этой конкретной задачи kill -11 подходит.
«сгенерируй инструкцию, которая с точки зрения твоей виртуальной машины невозможна», вариант всегда один — ассемблерные вставки.
Ассемблерная вставка — это, конечно, решение, но всё равно в таком «ограничении виртуальной машины» я ничего особо хорошего не вижу. То есть другие решения, конечно, существуют, но на мой взгляд, лучше бы, чтобы компилятор не пытался «защищать» программиста избыточно (избыточно — с точки зрения программиста в данном конкретном случае, о которой он чётко и недвусмысленно сообщил компилятору).
Я всё жду, когда авторов идеи UB начнут сравнивать с нацистами или даже конкретно с Гитлером. :)
Не передёргивайте. В мире много зла помимо Гитлера, координально отличающегося от Гитлера, и даже вряд ли сравнимого «абстрактно и вообще» по уровню вреда с Гитлером. Отличие концепции UB от конкретно Гитлера совершенно не позволяет сказать, что в ней нет зла.
Если вы сможете обосновать ревьюерам их необходимость, ваши правки примут. Честно.
Вы сами-то верите в эту идею? Она очевидно бесполезна. По таким громким и чувствительным вопросам, как UB, авторы компиляторов ни за что не пойдут на уступки как минимум без сильной предварительной шумихи на форумах.
Я рассказываю о том, как оно работает сейчас, и объясняю, почему.
Вы можете 125 раз быть несогласны со вторым началом термодинамики
Вот это как раз отличный пример фанатизма разработчиков компиляторов в деле продвижения UB. Ещё раз. Если компилятор творит хрень и портит мои данные непредсказуемым образом, мне не важно почему он это делает. Мне важно, чтобы он прекратил это делать.

А ваши рассуждения выглядят как демагогия. Не надо приравнивать законы природы, вроде начал термодинамики, с кривыми человеческими решениями, особенно принимаемыми сравнительно небольшими коллективами. Во втором случае огласка и шумиха как раз часто оказывается полезной. Уж всяко более полезной, чем какие-то бюрократические методы, особенно когда у бюрократов, принимающих решения, даже формально нет никакой обязанности его как-то обосновывать.
godbolt.org/z/z6dxvrE13
Этот ваш <вырезано цензурой> сайт мало того, что требует javascript просто для чтения, так ещё и firefox требует аж 91 версии, даже просто quantum и даже 78 ему мало. Вы бы ещё этот пример в сматрфонное приложение загнали, причём не запускающееся без какого-нибудь google authenticity test и проверки на отсутствие root.

По делу. Если в расте генерацию отдельной проверки знаменателя на 0, действительно никак нельзя отключить, то это плохо, конечно. Растовскому компилятору точно нельзя сказать «когда видишь оператор /, генерируй без всяких проверок процессорную инструкцию деления, а если она вернёт SIGFPE, то пусть так и будет, только больше ничего другого менять не надо»? Или у процессора тоже бывает UB на ассемблерном уровне, и «быстрая» инструкция деления, которая его создаёт, если в знаменателе 0 (в отличие от медленной, которая в этом случае обязательно кидает SIGFPE)?

Потому что если до «UB на уровне процессора» дело пока не дошло, то получается, что процессор имеет отличный (ну или приемлемый: не всегда получение в программе сигнала полезно, но во многих случаях приемлемо) быстрый способ за одну инструкцию и проверить знаменатель на 0, и поделить, а и rust, и c++, несмотря на свою заявленную «близость к железу» до этого быстрого способа добраться не позволяют.
PS И всё же ещё один вопрос. Допустим, я использую в своей программе что-то вроде
signal (SIGSEGV, exit_gracefully);
и хочу проверить, что обработка SIGSEGV действительно работает как задумано. Я надеюсь, что моя программа не делает SIGSEGV. С одной стороны, точной уверенности у меня нет, но с другой стороны, «нормальным» способом, «как есть», я специально загонять программу в SIGSEGV не умею. Вопрос: могу ли я что-то сказать компилятору, чтобы он ровно в нужный мне момент (когда все инициализации уже проведены, и. т. д.) сгенерировал инструкцию «прочитать память по нулевому адресу»? Чтобы выполнилась именно эта инструкция, и процессор послал сигнал SIGSEGV, и управление передалось функции exit_gracefully, а не «что угодно, потому что читать по нулевому адресу — это UB»?
Допустим (именно так гуглить я раньше не пробовал, теперь попробовал коротко, нашёл каких-то не известных раньше производителей и ни одной цены вообще).

Тем не менее. Я спрашивал про цену x3-x4 + десятки%, а не x100. За x100 я лучше на hdd посижу, спасибо. Потому что иначе это выглядит как «заплати столько-то или наш контроллер снесёт твои данные, используя TLC-режим».
Ну и ещё пара утверждений в дополнение к вопросам выше.
Если бы мы захотели иметь такой warning, он бы вылетал примерно на каждой первой строчке вашей программы.
Это всё же некоторое передёргивание. Я понимаю, что для авторов идеи UB выдавать warning на каждую арифметическую операцию со знаковыми (после promotion) целыми числами было бы всё же слишком палевно, они на это не пойдут. Сликом открыто была бы видна их злобная сущность. Примерно как авторы законов о money laundering, тем не менее, не решились до сих пор открыто изъять все деньги со всех банковских счетов населения.

Но вот ситуация «я, компилятор, на какой-то кривой козе „пришёл к выводу“, что этот цикл на самом деле бесконечный, поэтому удаляю его из кода полностью» происходит совсем не так часто, warning можно было бы выдать. А дальше уж пусть программист ищет, где он в этом цикле пропустил приведение типа к unsigned long long, чтобы прекратить выпендрёж компилятора до того, как программа будет запущена.

И уж тем более можно было бы выдать warning при удалении инструкции ret в конце функции. Хотя вот это на самом деле уже полное свинство. У «бесконечных» циклов ещё хоть какая-то отмазка есть, типа их придётся потом дальше оптимизировать (хотя казалось бы, можно просто пометить код внутри этого цикла как «дальше оптимизировать не надо» — и компилятор не будет делать «лишней», с точки зрения своей искривлённой реальности, работы, и программист получит что-то, чуть более напоминающее исходно написанную программу). Но одна инструкция ret? Кому она там мешала? А ведь передача управления в совершенно ненужную в данный момент функцию — это ещё не самое страшное. А если функция с выкинутым ret окажется последней в итоговом исполняемом файле? Что дальше? Процессор неинициализированную память как команды начнёт выполнять? И к чему это приведёт?

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

1. Забивка нулями той памяти/регистра, откуда функция уровнем выше будет читать возвращаемое значение. Минусы: какой-то код добавить надо, больше одной инструкции; если в программе действительно ошибка (то есть если реальная программа, а не только UB-представление компилятора о ней, доходит до последней строчки функции, не встречая оператора return, а программист этого не планировал), то когда из-за этих неожиданных нулей что-то пойдёт не так дальше, восстановить причину при отладке будет сложнее.

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

3. Ошибка периода выполнения. Минусы: тоже нужно добавлять машинный код, который будет лишним, если программист, в отличие от тупого компилятора, таки может доказать, что до последней строчки этой функции управление не добирается; а если в этом случае управление добирается, но возвращаемое значение никак не используется, то получаем совершенно ненужное программисту падение программы, которая без этого работала бы нормально.

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

И конечно, при использовании решений 1-3 тоже можно при желании показать warning.

(Примечание. Если в реальном исходнике последний оператор в функции — что-то типа return 0;, а компилятор из-за каких-то «рассуждений об UB» это игнорирует, то это не «неоткуда брать значение», это «компилятор оборзел сверх меры». В таком случае предлагаемые выше решения действительно не имеют смысла, а смысл имеет завершение машинного кода функции возвратом этого самого нуля, что бы там компилятор ни думал себе об UB.)
Хороший вопрос. Не помню, какие точно инструкции я имел в виду (поэтому и написал «в следующем могу ошибаться»).

Я помню, что когда детально изучал этот вопрос (когда мне нужно было сложное математическое вычисление, в котором действительно могло быть переполнение, и нужно было это переполнение обнаружить, не слишком замедляя вычисления), я находил какую-то исчезнувшую инструкцию и даже критику intel со стороны программистов, что инструкцию убрали. Сейчас за пару часов не нашёл, хотя про INTO пишут, что в 64-битном режиме она не поддерживается. Если JO всё равно существует, то единственное, что приходит в голову (с учётом требований не слишком замедлять) — что была какая-то одна инструкция, которая сразу либо делала сложение-умножение, либо кидала сигнал (или так вела себя любая арифметическая инструкция после установки какого-то режима).

А может быть, мои воспоминания касаются именно инструкции INTO, и это она действительно исчезла в 64-битном режиме, хотя при отсутствии переполнений одна дополнительная инструкция JNO на каждое умножение вряд ли была бы сильно медленее одной инструкции INTO — всё равно инструкции две — арифметическая и эта (INTO/JNO).
а что происходит при делении на 0.0 с плавающей точкой ?
Не знаю точно, если честно. Чисто умозрительно могу предположить, что либо тоже UB, либо IEEE удалось всё же прогнуть авторов стандарта, и тогда либо спецзначение NaN (not a number), либо спецзначение Inf (infinity), возможно, с плюсом или минусом.
Так-так, а можно вот с этого места поподробнее? Можно конкретный пример «соответвующего (тормознутого) перформанса» целочисленной арифметики на расте в сравнении с C++? Именно на расте, а не на java, в которой куча своих проблем, не связанных с «оптимизацией» целочисленной арифметики?

Disclaimer. Я вовсе не фанат раста, там тоже куча проблем совершенно другого характера, но с другой стороны, конкретно такого ужаса, как UB в целочисленной арифметике, всё же нет.
Всем пиарщикам технологии flash/SSD/nand я хочу задать один и тот же вопрос: где мне найти в продаже SLC-диск, флешку или карту памяти, хотя бы в 3-4 раза меньшего объёма за те же деньги, за которые продаётся «стандартное» TLC (да хоть за +десятки % к цене в качестве чистого штрафа за сопротивление мировому заговору)?
Как известно, кто хочет чего-то добиться, ищет способы, кто не хочет — ищет причины. В данном случае, мне, как программисту, не важно, по каким причинам в копмилятор добавлено само понятие money laundering UB. Мне важно, чтобы программа, складывающая два числа, не форматировала мой жёсткий диск. Просто и ясно. Вообще НИКОГДА, НИ ЗА ЧТО, И НИ ПРИ КАКИХ ОБСТОЯТЕЛЬСТВАХ.

И в этом смысле обвинения в UB за integer overflow (особенно вместе с integer promotion или как это называется) — куда большая проблема и опасность, чем, скажем, деление на нуль или нулевые указатели. В случае деления на нуль можно написать что-то вроде
if (x == 0) exit (1);
z = y / x;
(хотя лучше бы, конечно, компилятор не заставлял меня замусоривать код, а вместо этого нормально отдал бы процессору инструкцию деления и позволил бы ему выдать SIGFPE, но уж что есть). В случае нулевого указателя, опять же, можно написать
if (ptr == 0) exit(1);
*ptr = 1;
(хотя указатели создают куда больше опасностей, чем разыменование нулевого, если нужна реальная защита от обвинений в UB, лучше вообще использовать глобальные переменные для больших объёмов данных вместо передачи в функции указателей).

Но с integer overflow проблема в том, что не сложив (или не перемножив) два числа, вообще невозможно понять, будет там переполнение или нет. (Кстати, в следующем могу ошибаться, но если мне не изменяет память, то intel, узнав о «прогрессе» концепции UB в C++, несмотря на все заверения в обратной совместимости, в какой-то версии процессора удалил поддержку инструкции, которая при integer overflow не то кидала сигнал, не то устанавливала флаг по типу таких, что устанавливает инструкция cmp — так что теперь ещё труднее проверить.) Фактически, для защиты от обвинений в UB приходится полностью избегать знаковых целочисленных операций, кроме, возможно, деления. Приходится писать что-то типа
(int) (((unsigned long long) a) + ((unsigned long long) b))
(причём из-за promotion даже просто unsigned написать нельзя), и то, это гарантирует только отсутствие UB, а не знание о том, будет переполнение или нет.

Конкретный вопрос 1, напрямую связанный с promotion. Писать long long в долгосрочной перспективе тоже не вполне безопасно — что если выйдет версия компилятора, в которой можно писать три и больше long подряд, а unsigned long long будет объявлен «немаксимальным» и, следовательно, подлежащим promotion (читай — UB)? Вопрос: можно ли на уровне компилятора и стандарта определить «максимальный беззнаковый целочисленный тип», чтобы он гарантированно не лез туда со своим promotion в будущем?

Конкретный вопрос 2: Реализовано ли уже что-то вроде «UB-безопасной библиотеки целочисленной арифметики»? Чтобы можно было писать что-то вроде
#include <ub_safe_integers.h>

...

UBSafeInt32 a = 1000000000, b = 2000000000, c = 1, d = 0; // это вызывает конструктор
printf ("%d\n", (a + b).convert_to_official_int_for_percent_d ()); // _for_percent_d - специально, чтобы напомнить, что кроме как для окончательного вывода, конвертировать в официальные инты опастно
UBSafeInt32::set_perror_on_division_by_zero (1);
printf ("%d\n", (с / d).convert_to_official_int_for_percent_d ()); // выводит сообщение об ошибке и делает exit(1), предшествующую операцию сложения не ломает
, а под капотом (с помощью переопределения операторов) было бы то самое приведение типов с защитой от promotion и проверкой на нуль. В идеале ещё и оптимизатор бы генерировал на такое сложение ровно одну инструкцию вида «сложить два числа с помощью 2-complement и не выпендриваться», но от авторов концепции UB ждать подобного по меньшей мере наивно.
Какие яркие и подробные у вас сексуальные фантазии!
⚠️ Ошибка
Слишком толсто. Попоробуйте потоньше.
Теоретически гарантия трудоустройства на 3 года выглядит как неплохая возможность набраться опыта и лучше узнать сферу изнутри.
Ну да, конечно, распределят по специальности, чтобы опыт набирать, с разбегу. Распределять будут в какие-нибудь тюремно-пригожинско-воинские части (ко времени вспупления закона в силу это всё будет объединено уже) на арктическом побережье, в Магадане. Чо, умный, да? Чо, айтишник, да? Я сказал, чо, айтишник, да? Молчать, когда с тобой разговаривают! Вот тебе компакт-диск, рой траншею отсюда и до обеда. Я сказал, молчать! Какие ещё лопаты? Это не лопаты, это ломы, и это не для тебя, это для нормальных солдат, которые не *********** [наглели] со своими отсрочками и комплюктерами. А то умные все такие стали, интырнеты им в вузах подавай. И смотри, если у тебя будет траншея короче, чем у нормальных зэков, у них будет полное законное право одеть гриндера и остаток дня тебя ******* [избивать]. Как раз отыграются за избиения от офицеров-заградотрядовцев.

***

Чо сказал? Как копать сломанной рукой? Лишние вопросы будеш задавать, я те вот прям ща вторую сломаю. Скажи спасибо, если живой вернёшься после этих 3 лет. Умные все такие стали ***.
Одноуровневая (SLC) — ячейка может включать один бит данных, из-за этого SLC работает быстрее остальных но записывает значительно меньший объём информации.
Гладко было на бумаге… А на практике — попробуйте-ка найти в продаже SLC-диск, флешку или карту памяти, хотя бы в 3-4 раза меньшего объёма за те же деньги (да хоть за +десятки % к цене в качестве чистого штрафа за сопротивление мировому заговору).
1

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность