LINUX.ORG.RU

Хрупкие программы

 


0

2

Почему так бывает, что при -O0 программа работает нормально, а например при -O3 начинает падать, но не всегда. Чей тут косяк, программиста или gcc? Может ли использование static_cast и запрет неявных преобразований типов избежать такого поведения?



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

так, ты ничего не видел, точнее не видела, все понятно? Да, все понятно!

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

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

Давайте ещё в каждом доме ставьте розетки разной формы, напряжения и частоты так что придётся таскать over 9000 активных переходников. Должны быть стандарты, они упрощают жизнь.

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

Это третий страйк, я уже дважды ТСа ловил на выходе из образа.

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

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

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

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

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

Например, очень не хватает signed with NaN. Я себе в виде хидера реализовал такой тип. Вполне может быть платформа, где такой тип встроен аппаратно. И любое переполнение всегда дает NaN.

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

Почему бы тогда не включить такое поведение в стандарт Си и закрыть на этом вопрос с одним из случаев UB?

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

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

Проблема глубже всего этого вашего прогаммирования и айти, даже у Лизы второе альтер-эго мужик в лоcосинах, а ты хочешь чтобы эти кожаные мешки пришли к какому-то единому мнению - «Не дождетесь!» (с)

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

дак только же обсудили, что когда он делает все хорошо по кнопке получается какая-то срань.

anonymous
()

Помнится, во времена моей противоречивой молодости (нулевые), в gentoo если включить use флаг -O3, мир собирался какой-то очень странный. Падучий и зависающий. Поэтому для себя усвоил, что дальше -O2 жизни нет. А с -O0 бинарики оказывались слишком большие и медленные.

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

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

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

получается какая-то срань.

Миллионам мух это нравиться, они не могут ошибаться.

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

Ну вот сейчас он теперь и с -O2 падучий и зависающий если правильные -fno-… не включить и еще по-разному подшаманить и кое-где -O1 или вовсе -O0 поставить.

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

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

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

не должен тихо в углу гадить злобно хихикая.

Ну, так скажи, что надо и не надо - всем не угодишь.

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

К счастью, нет, отношусь к дилдосу крайне скептически.

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

Либо у тебя в программе UB, тогда косяк программиста.

Наиболее вероятный вариант.

dimgel ★★★★★
()

Чей тут косяк, программиста или gcc?

в 99.99% это UB которое программист упустил.

Dark_SavanT ★★★★★
()

Почему так бывает, что при -O0 программа работает нормально, а например при -O3 начинает падать, но не всегда. Чей тут косяк, программиста или gcc?

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

Может ли использование static_cast и запрет неявных преобразований типов избежать такого поведения?

Нет.

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

С некоторыми нюансами, которые тебе ещё не известны, будет.

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

Наблюдаемое поведение изменилось. До оптимизации программа вызывала printf, а после – puts.

Это не наблюдаемое поведение.

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

NULL-pointer и «нулевой адрес» это разные вещи.

Эти «разные вещи» различимы в рамках языка? (Допустим, что конвертация числа в адрес не является неопределенным поведением). Иначе получится парадокс - неразличимые разные вещи.

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

Допустим, что конвертация числа в адрес не является неопределенным поведением

С чего это?

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

С чего это?

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

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

C это высокоуровневый язык.

Поэтому ядро линукс - это куча из неопределенного поведения.

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

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

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

Компилятор должен всегда выбирать безопасный сценарий по умолчанию

А дальше вопрос, что понимать под «безопасный». В ассемблере отсутствие RET в конце функции обозначает, что должен выполниться код в следующей функции. Поэтому это естественный сценарий.

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

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

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

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

Эти «разные вещи» различимы в рамках языка?

Можно сделать различимыми. Например, ((void *)0) может отображаться в FFFF:FFFFFFFF

Так как валидный адрес (отличный от «нулевого адреса») можно получить только неязыковыми средствами.

В Си по стандарту валидный адрес должен быть адресом одного из объектов внутри программы. А значит его всегда можно получить через взятие адреса объекта.

Вплоть до того, что

int a[10];

*(a + 11) 

будет UB, так как в массиве всего 10 элементов и ссылка на 11-й элемент является невалидной.

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

А если нет возможности проверить, нефиг эту оптимизацию включать. Пусть пользователь включает ее сам отдельной опцией на свой страх и риск.

Он именно это и делает. Опция называется -O3. А «нефиг эту оптимизацию включать» называется -O0.

В общем случае, всегда нет возможности проверить.

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

Он именно это и делает. Опция называется -O3. А «нефиг эту оптимизацию включать» называется -O0.

При том кроме O0, O1, O2, O3 есть полный список оптимизаций которые есть в этих O.

https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

пример для O1

-O1  turns on the following optimization flags: 

-fauto-inc-dec 
-fbranch-count-reg 
-fcombine-stack-adjustments 
-fcompare-elim 
-fcprop-registers 
-fdce 
-fdefer-pop 
-fdelayed-branch 
-fdse 
-fforward-propagate 
-fguess-branch-probability 
-fif-conversion 
-fif-conversion2 
-finline-functions-called-once 
-fipa-modref 
-fipa-profile 
-fipa-pure-const 
-fipa-reference 
-fipa-reference-addressable 
-fmerge-constants 
-fmove-loop-invariants 
-fomit-frame-pointer 
-freorder-blocks 
-fshrink-wrap 
-fshrink-wrap-separate 
-fsplit-wide-types 
-fssa-backprop 
-fssa-phiopt 
-ftree-bit-ccp 
-ftree-ccp 
-ftree-ch 
-ftree-coalesce-vars 
-ftree-copy-prop 
-ftree-dce 
-ftree-dominator-opts 
-ftree-dse 
-ftree-forwprop 
-ftree-fre 
-ftree-phiprop 
-ftree-pta 
-ftree-scev-cprop 
-ftree-sink 
-ftree-slsr 
-ftree-sra 
-ftree-ter 
-funit-at-a-time
fsb4000 ★★★★★
()
Последнее исправление: fsb4000 (всего исправлений: 1)
Ответ на: комментарий от monk

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

Перечисли это «большинство». И для проверки на большинство перечисли «меньшинство». Упустим для простоты разные способы адресации (прямая, индексная, относительная и тп).

Например, ((void *)0) может отображаться в FFFF:FFFFFFFF

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

На счет системщины, на си нельзя работать с таблицей векторов прервывний x86 языковыми средствами.

должен быть адресом одного из объектов внутри программы.

Системщина – это не про объекты внутри программы.

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

Компиляторы заходят слишком далеко.

а к constexpr как относишься? Там вообще ж кошмар — компилятор может все сам посчитать и заменить на конечное значение и вызова функции не будет (даже inline подстановки). При чем это касается и случая, если функция не объявлена как constexpr, но удовлетворяет требованиям.

И алгоритмы из stl тоже та еще кака, где на банальном std::copy можно получить memcpy вместо цикла (но тут нехорошие программисты все подстроили, а не компилятор)

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

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