LINUX.ORG.RU

gcc-8 совсем поломанный

 


3

7

Я так понимаю в последних версиях gcc хипстеры вообще всё сишку решили сломать. Хотя пишут статейки что C никогда не был портабельным ассемблером, но ведь использовали его так и куча кода накопилась. Теперь этот весь код сломан. Например сброс знака по (a & 0x7fffffff) не работает и много всего вообще теперь не работает и писать теперь надо как на плюсах. И страшно бояться любого UB так как оно будет страшно падать на ровном месте и 2+2 будет 5. Особенно это опасно, если лет 30 устоявшиеся методы для решения задач были, и эти чувырлы с UB головного мозга это всё радостно ломают. Я так понимаю это делается специально, чтобы кому-то не было скучно на работе, а реального толку 0. Какой сейчас более-менее адекватный gcc, 5.4? Шланг не предлагать, он никогда не был компилятором, вообще. Это они весь сыр-бор и начали. Я так понимаю реально там полезное сейчас только в C++ делают, в C только ломают.

★★★★★

http://delivery.acm.org/10.1145/2910000/2908081/p1-memarian.pdf

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

из этого можно сделать очевидный вывод: тебе с ними не по пути.

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

anonymous
()

Эх. Я уж было заскучал по постам скотинки.

Deleted
()
Ответ на: комментарий от slapin
$ clang --version
clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
$ clang test.c -fsanitize=undefined
test.c:7:50: warning: '^' within '|' [-Wbitwise-op-parentheses]
                r += ((r * 20891 + *s *200) | *s ^ 4 | *s ^ 3 ) ^ (r >> 1);
                                            ~ ~~~^~~
test.c:7:50: note: place parentheses around the '^' expression to silence this warning
                r += ((r * 20891 + *s *200) | *s ^ 4 | *s ^ 3 ) ^ (r >> 1);
                                                 ^
                                              (     )
test.c:7:59: warning: '^' within '|' [-Wbitwise-op-parentheses]
                r += ((r * 20891 + *s *200) | *s ^ 4 | *s ^ 3 ) ^ (r >> 1);
                                                     ~ ~~~^~~
test.c:7:59: note: place parentheses around the '^' expression to silence this warning
                r += ((r * 20891 + *s *200) | *s ^ 4 | *s ^ 3 ) ^ (r >> 1);
                                                          ^
                                                       (     )
2 warnings generated.
$ ./a.out 
test.c:7:26: runtime error: signed integer overflow: 481340559 * 20891 cannot be represented in type 'int'
test.c:7:19: runtime error: signed integer overflow: 1752892743 + 454394588 cannot be represented in type 'int'
result: 1777607782 69f42466
result: 2147483548 7fffff9c

Теперь чиним, меняем:

int r = 0;
int foo2(int c)
На:
unsigned r = 0;
int foo2(unsigned c)
И получаем:
$ ./a.out 
result: 1479383358 582d993e
result: 2147483548 7fffff9c
В чём необходимость использования знакового целочисленного, если точно знаешь что будет переполнение?

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

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

а набросить?

anonymous
()

согласен. gcc надо переписать на golang

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

Стандарт мне ни стандарт яскозал!
Стандартное поведение

Ты же понимаешь, что ты поехавший?

anonymous
()

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

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

Хорошая статья. Меня тут недавно пытались убедить, что в C всё просто и очевидно, а мои вопросы по стандарту говорят о том, что мне не стоит программировать.

Хотя ясно (умным людям вроде меня), что стандарт C недоопределён во многих вещах.

anonymous
()
Ответ на: комментарий от slapin
$ gcc -fsigned-char -O2 ub.c
$ ./a.out 
result: 1777607782 69f42466
result: 2147483548 7fffff9

$ gcc -funsigned-char -O2 ub.c
$ ./a.out 
result: -369875866 e9f42466
result: 2147483548 7fffff9c

На ARM'ах char беззнаковый.

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

Это то понятно, просто почему во всех предыдущих компиляторах всё нормально работает. Ищу пока какая оптимизация гадит.

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

Ищу пока [...]

Уже ведь сказали: целочисленное знаковое переполнение. Новый GCC просто лучше выражение анализирует.

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

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

http://esxi.z-lab.me:666/~exl_lab/screens/unsigned_char_arm.png

EXL ★★★★★
()

Например сброс знака по (a & 0x7fffffff) не работает и много всего вообще теперь не работает и писать теперь надо как на плюсах.

У вас наверное а 64-битное и поэтому вы получаете не тот результат? Ваш код как никак подвязан к 32 битам.

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

Потому что злые модераторы могут сказать что это реклама и удОлить. Так и живём.

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

в цикле к цулому r всегда плюсуется положительное число. Компилятор сщитает что результатом работы цикла не может быть отрицательное значение в r (кроме как через переполнение которое UB). А следовательно последняя команда (r & 0x7fffffff) - лишняя так как никогда (кроме UB на которое пофиг) не меняет результат.

Вот, внятное объяснение. Непонятно, чего ещё ТС'у надо.

i-rinat ★★★★★
()
Ответ на: комментарий от zaz

Компилятор сщитает что результатом работы цикла не может быть отрицательное значение в r (кроме как через переполнение которое UB).

А XOR ты не заметил?

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

А XOR ты не заметил?

Если r положителен, то (r >> 1) тоже положителен. Xor положительного с положительным не даст отрицательное число.

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

А я думал такие как ты только в байках бывают.

t184256 ★★★★★
()
Ответ на: комментарий от i-rinat

кроме как через переполнение которое UB

целочисленное переполнение всегда Defined и весьма хорошо задокументированное поведение. На Лоре Это уже обсуждалось.

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

на X86 и ARM это односится ко всем целым. Есть железо где это не так, но я даже затрудняюсь вспомнить название архитектуры.

cvv ★★★★★
()

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

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

Понятно, что и знаковое, и беззнаковое компилируются в один и тот же код в случае, если знаковое - это 2's complement. Не определена именно семантика переполнения знаковых целых в языке Си.

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

Не нашёл ни одного источника, который бы это подтверждал. Везде написано, что по стандарту signed overflow == UB. И заодно, как архитектура связана с переполнением? Разве не авторы компилятора решают что делать в той или иной ситуации?

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

Проблема в том что у GCC под ARM по непонятным для меня причинам сhar - беззнаковый (0-255).

Я где-то читал, что беззнаковый char был сделан в угоду производительности на старых ARM'ах. Но, возможно, есть какие-либо другие причины.

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

Наверное я попутал стандарты языка и документацию на процессоры.

И заодно, как архитектура связана с переполнением?

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

Разве не авторы компилятора решают что делать в той или иной ситуации?

В случае С/С++/Ада - нет. В случае матлаб или октавы - да.

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

Ты имеешь ввиду что 2's complement не прописан собственно в стандарте языка?

Хм ... Наверное так и есть ...

cvv ★★★★★
()

Я, конечно, не сишник, но

страшно бояться любого UB так как оно будет страшно падать на ровном месте

- это разве не универсально здравый смысл?

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

Чувак, даже шестой gcc — говно! Потому как компиляющийся ранее безо всяких ошибок код в gcc начинает срать насчет всяких «трамплинов» и т.п. И приходится как минимум добавлять в Makefile ключ -Wno-trampolines. Иначе как ты вложенные функции сделаешь?

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

Компилятор должен просто компилировать то, что ему написали. Если он начинает вертеть носом, то это не компилятор, а говно!

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

anonymous
()

А свой компилятор не хочешь написать?

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

Тут надо заглянуть в С11. На 100 процентов не уверен, но мне казалось что это в конце концов туда внесли

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

2.95?

Нет - 2.95.3 :-)

Хотя на самом деле это тоже было какоето недоразумение. Я уже не помню почему ...

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

существуют три основных двоичных представления знаковых чисел.

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

В случае С/С++/Ада - нет. В случае матлаб или октавы - да.

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

Deleted
()

Автору просто нужно компилять весь свой код с -fwrapv и прочими -f, так любимыми Линусом Торвальдсом.

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

Что ж ты будешь делоц, если у тебя sizeof(int) != 4 вылезет?

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

А видел ли кто этот стандарт? Жадные твари из ISO хотят за текст стандарта деньги, и я не знаю никого кто бы его купил. Может там всё совсем иначе чем в драфтах?

hateyoufeel ★★★★★
()
Последнее исправление: hateyoufeel (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.