Разрабатывая сомнительную претензию , я написал эту небольшую тестовую программуnoway.c
int proveit()
{
unsigned int n = 0;
while (1) n++;
return 0;
}
int main()
{
proveit();
return 0;
}
Тестируя это, я получаю:
$ clang -O noway.c
$ ./a.out
zsh: illegal hardware instruction ./a.out
Wat.
Если я компилирую без оптимизации, он зависает, как и ожидалось. Я посмотрел на сборку, и без всех наворотов main
функция выглядит так:
_main: ## @main
pushq %rbp
movq %rsp, %rbp
ud2
Где, ud2
по-видимому, инструкция специально для неопределенного поведения. Вышеупомянутое сомнительное утверждение «функция, которая никогда не возвращается - UB», подкреплено. Мне все еще трудно поверить, хотя. В самом деле!? Вы не можете безопасно написать спин-петлю?
Итак, я думаю, мои вопросы:
- Это правильное прочтение того, что происходит?
- Если да, может ли кто-нибудь указать мне какой-нибудь официальный ресурс, который это проверяет?
- В какой ситуации вы бы хотели, чтобы этот тип оптимизации происходил?
Соответствующая информация
$ clang --version
Apple clang version 11.0.0 (clang-1100.0.20.17)
Target: x86_64-apple-darwin18.6.0
Thread model: posix
InstalledDir: /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
c
standards
undefined-behavior
luqui
источник
источник
int n = 0
===>unsigned int n = 0;
или еще лучше ..while (1);
unsigned int
Ответы:
Если вы получите ud2 для кода, который сейчас находится в вопросе, то компилятор не является соответствующим компилятором Си. Вы можете сообщить об ошибке компилятора.
Обратите внимание, что в C ++ этот код будет на самом деле UB. Когда были добавлены потоки (C11 и C ++ 11 соответственно), была введена прямая гарантия прогресса для любого потока, включая основной поток выполнения программы, которая не является многопоточной.
В C ++ все потоки должны в конечном итоге прогрессировать, без исключений. Однако в Си цикл, управляющее выражение которого является константным выражением, не требуется для выполнения. Насколько я понимаю, C добавил это исключение, потому что во встроенном кодировании уже было обычной практикой использовать a
while(1) {}
для зависания потока.Подобный вопрос с более подробными ответами
источник
ud2
код C, но спасибо за то, что вы включили информацию о гарантии продвижения C ++ (термин, который я, вероятно, смогу исследовать), о котором я действительно спрашивал, но который был оптимизирован как Я готовил вопрос.