Enquanto investigava uma alegação duvidosa , escrevi este pequeno programa de testenoway.c
int proveit()
{
unsigned int n = 0;
while (1) n++;
return 0;
}
int main()
{
proveit();
return 0;
}
Testando isso, recebo:
$ clang -O noway.c
$ ./a.out
zsh: illegal hardware instruction ./a.out
Wat.
Se eu compilar sem otimizações, ele trava como esperado. Eu olhei para a montagem e, sem todos os sinos e assobios, a main
função fica assim:
_main: ## @main
pushq %rbp
movq %rsp, %rbp
ud2
Onde ud2
está aparentemente é uma instrução específica para comportamento indefinido. A afirmação duvidosa acima mencionada, "Uma função que nunca retorna é UB", é reforçada. Eu ainda acho difícil de acreditar. Realmente!? Você não pode escrever com segurança um loop de rotação?
Então, acho que minhas perguntas são:
- Esta é uma leitura correta do que está acontecendo?
- Se sim, alguém pode me indicar algum recurso oficial que o verifique?
- Em que situação você deseja que esse tipo de otimização ocorra?
Informações relevantes
$ 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
fonte
fonte
int n = 0
===>unsigned int n = 0;
ou melhor ainda ..while (1);
unsigned int
Respostas:
Se você obtiver o ud2 para o código que está agora em questão, o compilador não é um compilador C em conformidade. Você pode relatar um bug do compilador.
Observe que em C ++ esse código seria realmente UB. Quando os threads foram adicionados (C11 e C ++ 11, respectivamente), foi criada uma garantia de progresso para qualquer thread, incluindo o thread de execução principal de um programa que não é multithread.
No C ++, todos os threads devem eventualmente progredir, sem exceções. No entanto, em C, um loop cuja expressão controladora é uma expressão constante não é necessário para progredir. Meu entendimento é que C adicionou essa exceção porque já era prática comum na codificação incorporada usar a
while(1) {}
para travar o thread.Pergunta semelhante com respostas mais detalhadas
fonte
ud2
código C, mas obrigado por incluir as informações sobre a garantia de progresso avançado do C ++ (um termo que parece que eu vou pesquisar), que é o que eu realmente estava perguntando, mas que foi otimizado como Eu estava preparando a pergunta.