Доступен (https://gcc.gnu.org/ml/gcc-announce/2017/msg00002.html) корректирующий релиз набора компиляторов GCC 7.2 (https://gcc.gnu.org/gcc-7/), в котором проведена работа по исправлению ошибок, регрессивных изменений и проблем с совместимостью. По сравнению с версией GCC 7.1 (https://www.opennet.me/opennews/art.shtml?num=46487) в GCC 7.2 отмечено 95 исправлений (https://gcc.gnu.org/gcc-7/changes.html), в основном связанных с устранением регрессивных изменений. Напомним, что начиная с ветки GCC 5.x в проекте внедрена новая схема нумерации выпусков: версия x.0 используется в процессе разработки, корректирующие выпуски формируются с номерами x.2.0, x.3.0 и т.д. Новые возможности развиваются в экспериментальной ветке GCC 8.0, на базе которой будет сформирован следующий значительный релиз GCC 8.1.
URL: https://gcc.gnu.org/ml/gcc-announce/2017/msg00002.html
Новость: http://www.opennet.me/opennews/art.shtml?num=47021
А позор типа
for (int n = 0; n < arr_length; ++n) make_zashibis(arr[n]);
...
if (arr) { ... } /* выкинуто gcc по причине undefined behaivour */GNU-макаки исправили или нет ??
Выкинуть нужно анонима. А gcc всё сделал правильно
Ты полный пример можешь дать? И версию компилятора заодно...Потому что при таком вызове arr у тебя измениться не может, только его содержимое.
GCC6.3 и старая opera , моя прелесть
Это просто сотрясения воздуха, а не ответ на вопрос.Смотри, берём такой код:
void foo(int);
int bar(int **);
void baz();int main()
{
int *arr;
int arr_len = bar(&arr);
for(int n = 0; n < arr_len; n ++)
foo(arr[n]);
if(arr)
baz();
return 0;
}Вызываем gcc:
gcc -O2 -S tmp.c -Wall -fverbose-asm
Получаем:
main:
.LFB0:
.cfi_startproc
pushq %rbp #
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
pushq %rbx #
.cfi_def_cfa_offset 24
.cfi_offset 3, -24
subq $24, %rsp #,
.cfi_def_cfa_offset 48
movq %rsp, %rdi #,
movq %fs:40, %rax #, tmp106
movq %rax, 8(%rsp) # tmp106, D.1788
xorl Йx, Йx # tmp106
call bar #
testl Йx, Йx # arr_len
jle .L6 #,
subl $1, Йx #, tmp101
xorl Кx, Кx # ivtmp.7
leaq 4(,%rax,4), %rbp #, _26
.p2align 4,,10
.p2align 3
.L5:
movq (%rsp), %rax # arr, arr
movl (%rax,%rbx), Мi # *_10, *_10
addq $4, %rbx #, ivtmp.7
call foo #
cmpq %rbp, %rbx # _26, ivtmp.7
jne .L5 #,
.L6:
cmpq $0, (%rsp) #, arr
je .L4 #,
xorl Йx, Йx #
call baz #
.L4:
xorl Йx, Йx #
movq 8(%rsp), %rdx # D.1788, tmp107
xorq %fs:40, %rdx #, tmp107
jne .L11 #,
addq $24, %rsp #,
.cfi_remember_state
.cfi_def_cfa_offset 24
popq %rbx #
.cfi_def_cfa_offset 16
popq %rbp #
.cfi_def_cfa_offset 8
ret
.L11:
.cfi_restore_state
call __stack_chk_fail #
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Gentoo 6.3.0 p1.0) 6.3.0"
.section .note.GNU-stack,"",@progbitsМетка .L6 это тот самый if, который по твоим словам должен быть выкинут из-за UB. И мы чётко видим, что он не выкидывается.
edit: форум смешно покорёжил att синтаксис. Но суть видна и так.
Тем не менее,было такое дело , было https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49820
так та бага вообще не о том.
Там юзер хотел "проверить int на переполнение". Ему и объяснили, что это UB.
Можно было просто дать ссылку https://godbolt.org/g/Wy4TPn
И нагляднее, и проще.
То есть ты сначала разыменовываешь указатель, а потом проверяешь, не нулевой ли он? Молодец, чё.
А в чем проблема ?? Если N<0, он и не разименовывается.
Вы сами написали: "/* выкинуто gcc по причине undefined behaivour */".
Неопределенное поведение потому оным и зовется, что оно неопределенное и в стандарте не прописано.
Не, нормальные люди не допускают UB. Хотя выше пример исковеркан - к примеру, там, вероятно, if (!arr) имелось в виду. И навреняка ещё куча всего покалечена, так что не понять. Где там те исходники оперы ловить - не знаю и разбираться не хочу. Охота возиться с варезом - флаг в руки. Или ещё куда.
ИМХО UB должно не компилироваться или компилироваться, но не выкидываться, т.к. это уже UB^2 ( но это лишь моё мнение основанное не на тоннах непонятного кода а на аналогией с жизнью в реальном мире и правилах по технике безопасности, хотя последнее время читая посты про вживление ИТ мира в реальность складывается впечатления что они слишком ортогональны )
Вообще-то, в стандарте С как раз описано неопределённое поведение.
Используй clang, какие проблемы то?
Да, это ошибка компилятора, но что тут позорного? Хорошую оптимизацию сделать сложно, а при создании сложных вещей легче ошибиться, чем при создании "Hello, world". Поэтому когда программист включает оптимизацию, он должен понимать, что делает. Также он должен понимать, что люди ошибаются, кроме него самого, разумеется.
> GNU-макаки исправили или нет ??Ну макак я, допустим, ещё пропущу, но вот пи#####ов держите пожалуйста при себе. ;)
Нецензурщину в треде вырезал.
> Нецензурщину в треде вырезал.Ты конечно молодец, но у тебя это вышло откровенно говоря фигово. Лучше бы ты её зацензурил. А то в итоге вырезал и кусок кода который обсуждали вверху. И получили мы обсуждение без начала.
Так держать модераторы.
В общем, на сей случай есть набор ключей,который придется теперь писать везде
-fno-strict-aliasing
-fno-strict-overflow
-fwrapv
-fno-delete-null-pointer-checks
Диванные хаятели gcc в треде! все в машину!Сколько себя помню, уже 15 лет сознательной окололинуксовой жизни, натурально считается образцом поведения невзначай упомянуть фразу "глюки GCC". Это поднимает ЧСВ у хацкеров. Ведь не ваш г0внокод виноват, а нехороший такой компилятор!
Чаще всего все глюки из-за оптимизации. И они действительно есть. Один очень хорошо повторялся: strlen на пустой строке сегфолтился по выходу за пределы строки (\0 точно был). Возможно неверно запомнил, но поведение примерно такое было. Не хочется глюков, -O0. Вот и всё.
Если бы не gcc - где бы час находился бы наш мир!!
А гляки/баги есть везде!(в оприори) - где то больше где то меньше, но это не важно для ядерной станции....
Он был бы несомненно лучше и удобнее
Учитывая, что я лично нашёл не менее 5 примёров, когда GCC генерировал плохой код, то даже не знаю.Причем в паре раз это было kernel miscompilation leading to kernel panics/Ooops'es.
Впрочем, с другими компиляторами так тесно не общался, и могу предположить, что для проектов такого масштаба - это норма.
// b.
> Впрочем, с другими компиляторами так тесно не общался, и могу предположитьЕсть такой линкер под оффтопик UniLink (ftp://ftp.styx.cabel.net/pub/UniLink/). Неплохой линковщик, который много чего умеет (линковать объектники от разных компиляторов, например, в том числе и gcc). Почитать его довольно большой history (там ещё и от ранних релизов архив лежит), в котором то и дело "Добавлено <что-нибудь> для очередной ошибки <компилятора>", немного удивляешься, как оно вообще в принципе работает и сколько в этом всём костылей.
UniLink привожу потому, что он не привязан к "особенностям" конкретного компилятора, и поэтому автору приходится много работать, чтобы обойти все эти особенности.
Наткнулся на такую засадку небольшую в ГЦЦ:
Не считает поле "int" в "const union" за "const int".Из-за этого такое поле нельзя вставить в switch/case...
Мелочь, а неприятно.Вот например такой код не компилится.
http://rextester.com/EOQCD80556
Со мной всё в порядке?
> Не считает поле "int" в "const union" за "const int".Если копнуть эту тему глубже, то получается, что он скорее всего собирает этот const union в рантайме, что тоже не хорошо..
> скорее всего собирает этот const union в рантаймене, не подтвердилось
Вообще ни один компилер не компилит.Щас на раст перейду с джавой.
> Наткнулся на такую засадку небольшую в ГЦЦ:
> Не считает поле "int" в "const union" за "const int".
> Из-за этого такое поле нельзя вставить в switch/case...
> Мелочь, а неприятно.
> Вот например такой код не компилится.
> http://rextester.com/EOQCD80556
> Со мной всё в порядке?Все правильно:
www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
> 6.8,4,2
> The expression of each case label shall be an integer constant expression and no two of the case constant expressions in the same switch >statement shall have the same value after conversion.constant expr != const foo
Приведённая цитата из стандарта не о том. Переводится как "в case должен быть const int, и не допускается два одинаковых const int".Вот смотрите. Есть константный union. Помеченный как const, и инициализированный как const. Который прописывается в секцию данных.
Логично, что все его поля тоже const.
Но если пытаться инициализировать его полем константу - компилятор ругается..
И та же ситуация с const struct.
>> integer constant expression
> Приведённая цитата из стандарта не о том. Переводится как "в case должен
> быть const int, и не допускается два одинаковых const int".Вы серьезно или издеваетесь? o_O
> Вот смотрите. Есть константный union. Помеченный как const, и инициализированный как const.
> Который прописывается в секцию данных.Еще раз: сonst var = только на чтение, но значение может быть присвоенно в рантайм
сonstant expr = компайлтайм вычисляемое выражение.
И что в данной ситуации пошло так?
Почему const union считается constexpr?Кстати, если заменить union на struct - тогда ситуация переменная в зависимости от версии компилятора.
> Приведённая цитата из стандарта не о том. Переводится как "в case должен быть const int, и не допускается два одинаковых const int".О том. Вы почитайте теперь, что, с точки зрения стандарта, есть const int:
"An integer constant expression99) shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof operator".
> Вы почитайте теперь, что, с точки зрения стандарта, есть const intДа, всё именно так, спасибо.
Раскомментируйте "case z":
Во-первых, в case, как уже выше сказали, должен быть constant expression. Const-qualified переменная типа union таковым не является до C++11 (у вас gcc 5.1, который по умолчанию компилирует С++03). Во-вторых, запись в один член union и чтение из другого - undefined behavior, которого в принципе не допускается в constant expression. А значит даже в C++11 ваш код не является constant expression (т.е. компилятор обязан рассматривать его как runtime код).
> запись в один член union и чтение из другого - undefined behaviorоткуда такие глубокие познания в С++ ?
Из стандарта. [class.union], [basic.life].
> компилятор обязан рассматривать его как
> runtime код).Я извиняюсь, допустил небольшой косяк в коде, описав константу внутри функции (сделав её инициализируемой в рантайме).
Вот исправленный пример, где она не инициализирована в рантайме:Компилятор clang превращает её в 0x04030201 , т.е. воспринимает как const-expr, а gcc кастит в рантайме.
П.С. Создал баг на gcc. Закрыли с комментом "it has to be a constant literal".
>> компилятор обязан рассматривать его как
>> runtime код).
> Я извиняюсь, допустил небольшой косяк в коде, описав константу внутри функции (сделав
> её инициализируемой в рантайме).
> Вот исправленный пример, где она не инициализирована в рантайме:
> https://godbolt.org/g/zxEwSnЭто не меняет ровным счетом ничего.
template< int N >
struct foo
{
static const int value = N;
};enum { constant = 10 };
int main()
{
const int n = constant;
return foo< n >::value;
}Это собирается и возвращает 10. Это демонстрирует, что n - это constant expression.
> Компилятор clang превращает её в 0x04030201 , т.е. воспринимает как const-expr, а
> gcc кастит в рантайме.Нет, вы путаете constant expression со способностью компилятора к оптимизациям.
А одобренный D где?