LINUX.ORG.RU

g++ internal compiler error при компиляции говнокода с -O2

 , ,


0

1

Итак, берём лютый говнокод

int main()
{
	auto f = [](void* ptr) { goto *ptr; };

	f(&&label);

label:
	return 0;
}
и скармливаем его g++. Пока уровень оптимизаций меньше -O2, то он компилируется. Работает везде по-разному. У меня падает с
*** stack smashing detected ***: ./a.out terminated
Aborted (core dumped)
на http://melpon.org/wandbox/ мирно завершается с кодом возврата 0.

Но стоит только включить уровень -O2... (компиляция на вышеупомянутом сайте, gcc HEAD 7.0.0 20161113 (experimental))

prog.cc: In function 'main()::<lambda(void*)>':
prog.cc:3:23: internal compiler error: Segmentation fault
  auto f = [](void* ptr) { goto *ptr; };
                       ^
0xaf60df crash_signal
	/home/heads/gcc/gcc-source/gcc/toplev.c:338
0xb2c48d cleanup_control_flow_bb
	/home/heads/gcc/gcc-source/gcc/tree-cfgcleanup.c:250
0xb2c741 cleanup_tree_cfg_1
	/home/heads/gcc/gcc-source/gcc/tree-cfgcleanup.c:702
0xb2c741 cleanup_tree_cfg_noloop
	/home/heads/gcc/gcc-source/gcc/tree-cfgcleanup.c:766
0xb2c741 cleanup_tree_cfg()
	/home/heads/gcc/gcc-source/gcc/tree-cfgcleanup.c:817
0xa403c4 execute_function_todo
	/home/heads/gcc/gcc-source/gcc/passes.c:1918
0xa4137b execute_todo
	/home/heads/gcc/gcc-source/gcc/passes.c:2015
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <http://gcc.gnu.org/bugs.html> for instructions.

Самая младшая падающая версия — gcc 4.6.4 (на вышеупомянутом сайте). Версии проверял не все, только несколько верхних и нижних плюс пару промежуточных, они крашатся. Думаю, крашатся все промежуточные.

Похоже, разработчики g++ не были готовы к тому, что их расширение «Labels as Values» будут скрещивать с лямбдами.

Кстати, clang++ отвергает код с такой формулировкой:

prog.cc:3:27: error: indirect goto in function with no address-of-label expressions
        auto f = [](void* ptr) { goto *ptr; };
                                 ^
Хорошая защита от говнокода, но некоторым она не нравится: https://llvm.org/bugs/show_bug.cgi?id=18658

Воспользуемся воркэраундом, приведённом в багрепорте и изменим лямбду:

auto f = [](void* ptr) { goto *ptr; crap: void *pcrap = &&crap; };
clang++ компилирует и не падает. И что самое забавное — g++ тоже перестаёт падать!

При этом g++ начинает лучше оптимизировать код: в первоначальной версии кода, на уровне -O1 остаётся вызов лямбды, а в версии с dummy-меткой в лямбде main компилируется просто как обнуление eax и возврат. clang++ с -O1 оптимизирует main до такого же состояния. Правда, я подозреваю, это не результаты инлайнинга, а результаты выкидывания кода с UB.

Такие дела.

Что касается багрепорта — я его организую как только мне выдадут доступ к gcc-шной багзилле.

★★★

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

Лютый говнокод :-)

anonymous
()

Реально падает. gcc-5.4.0:

> g++ -O2 -std=c++14 shit.cc -o shit          
shit.cc: In function 'main()::<lambda(void*)>':
shit.cc:3:26: internal compiler error: Segmentation fault
     auto f = [](void* ptr) { goto *ptr; };
                          ^
Please submit a full bug report,
with preprocessed source if appropriate.
See <https://bugs.gentoo.org/> for instructions.

hateyoufeel ★★★★★
()

Я с расширением «Labels as Values» аж целых два бага зарепортил (притом для Си, без всяких плюсов) https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66123 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66178 так что ничего удивительного

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

Мне страшно даже представить, что нужно было делать, чтобы на это напороться.

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

UB точно нет?

UB всё же относится к сгенерированному коду, разве нет? А тут компилятор падает.

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

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

Мне было интересно, заинлайнит ли g++ лямбду так, что UB станет кагбэ и не UB.

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

«говнокод» — у меня синоним «код с UB»

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

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

Ты понял, что я имел в виду «перестанет падать с '*** stack smashing detected ***'».

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

Значит ты меня понял, но долбился в глаза когда читал :)

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

На невалидных входных данных валится говнокод, те g++.

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

А ХЗ как принято у них, нужно ли там указывать самую раннюю версию с которой она начала валится, или самую позднюю, или можно вообще любую на которой оно валится. Если что, поправят. Там даже уже кто-то откомментировал, начиная с каких ревизий они валится

Confirmed. Started either with r160123 or r160124.
I mean r160122 or r160124.

В общем, они там разберутся

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