최적화되지 않는 무한 빈 루프를 만들려면 어떻게 해야 합니까?
C11 표준은 일정한 제어식을 가진 반복문을 최적화하지 않아야 함을 암시하는 것으로 보입니다.저는 이 답변에서 조언을 얻고 있습니다.이 답변은 표준 초안의 섹션 6.8.5를 구체적으로 인용하고 있습니다.
제어식이 상수식이 아닌 반복문은 구현에 의해 종료되는 것으로 간주될 수 있다.
이 답변에서 이 루프는while(1) ;
최적화의 대상이 되어서는 안 됩니다.
그러면 Clang/LLVM은 왜 아래 루프를 최적화합니까? (와 컴파일)cc -O2 -std=c11 test.c -o test
)?
#include <stdio.h>
static void die() {
while(1)
;
}
int main() {
printf("begin\n");
die();
printf("unreachable\n");
}
내 기계에서, 이것은 인쇄된다.begin
그러면 부정한 명령으로 크래시됩니다(a).ud2
뒤에 놓인 함정die()
godbolt 에서는, 다음의 콜 후에 아무것도 생성되지 않는 것을 확인할 수 있습니다.puts
.
Clang이 무한 루프를 출력하도록 하는 것은 놀라울 정도로 어려운 작업입니다.-O2
- 여러 번 테스트 할 수 있는 동안volatile
내가 원하지 않는 메모리 판독을 수반하는 변수입니다.이런 식으로 하면
#include <stdio.h>
static void die() {
while(1)
;
}
int main() {
printf("begin\n");
volatile int x = 1;
if(x)
die();
printf("unreachable\n");
}
...딸랑딸랑 프린트begin
이어서unreachable
마치 무한 루프가 존재하지 않는 것처럼요
최적화가 켜진 상태에서 Clang이 메모리 액세스 없이 적절한 무한 루프를 출력하도록 하려면 어떻게 해야 합니까?
C11 규격에서는 다음과 같이 기술되어 있습니다.
그의 지배 표현은 아닌 상수 expression,156 없는 입출력 작업을 수행한 반목문 탭과 그 신체에서 아무런 동기화 또는 원자 단위 연산을 수행하는 것, 표현 있거나 지배, 그 expression-3(에 대한 진술의 경우),가 구현에 의해 수행될 것 휘발성 개체에 액세스 하지 않는다.inate.157)
두 개의 풋노트는 규범적이지 않지만 유용한 정보를 제공합니다.
156) 생략된 제어식은 정수인 0이 아닌 상수로 대체한다.
157) 종료를 증명할 수 없는 경우에도 빈 루프를 제거하는 등의 컴파일러 변환을 가능하게 합니다.
당신의 경우,while(1)
는 매우 명확한 상수 표현이기 때문에 구현에 의해 종료되는 것으로 간주되지 않을 수 있습니다.이러한 구현은 "for-ever" 루프가 일반적인 프로그래밍 구조이기 때문에 절망적으로 무너질 것입니다.
그러나 루프 후에 "도달할 수 없는 코드"에 무슨 일이 일어나는지 내가 아는 한 잘 정의되지 않았습니다.하지만, 쨍그랑거리는 정말로 매우 이상한 행동을 합니다.기계 코드와 gcc(x86) 비교:
gcc 9.2-O3 -std=c11 -pedantic-errors
.LC0:
.string "begin"
main:
sub rsp, 8
mov edi, OFFSET FLAT:.LC0
call puts
.L2:
jmp .L2
쨍그랑9.0.0-O3 -std=c11 -pedantic-errors
main: # @main
push rax
mov edi, offset .Lstr
call puts
.Lstr:
.asciz "begin"
gcc는 루프를 생성하고 clang은 숲으로 들어가 오류 255와 함께 종료합니다.
나는 이것이 쨍그랑거리는 비호환적인 행동이라고 생각한다.저는 당신의 예를 다음과 같이 더 확장하려고 했습니다.
#include <stdio.h>
#include <setjmp.h>
static _Noreturn void die() {
while(1)
;
}
int main(void) {
jmp_buf buf;
_Bool first = !setjmp(buf);
printf("begin\n");
if(first)
{
die();
longjmp(buf, 1);
}
printf("unreachable\n");
}
C11을 추가했습니다._Noreturn
컴파일러를 지원하려고 합니다.이 기능은, 그 키워드만으로 행업 하는 것이 분명합니다.
setjmp
첫 번째 실행 시 0을 반환하기 때문에 이 프로그램은 그냥 에 충돌합니다.while(1)
여기서 정지하고 "slashing"만 인쇄합니다(\n flushing stdout).이것은 gcc에서 발생합니다.
루프가 단순히 제거된 경우 "begin"을 두 번 인쇄한 후 "unreachable"을 인쇄해야 합니다.단, clang(godbolt)에서는 종료 코드 0을 반환하기 전에 "begin"을 1회 인쇄한 후 "unreachable"을 반환합니다.그건 네가 어떻게 말하건 잘못된 거야.
여기서 정의되지 않은 동작을 주장하는 사례를 찾을 수 없습니다.따라서 제 견해로는 이것이 clang의 버그라고 생각합니다.어쨌든, 이 동작에 의해, 임베디드 시스템등의 프로그램에서는, 쨍그랑 소리가 100% 무효가 됩니다.이 프로그램에서는, 프로그램의 행업(워치독을 기다리는 동안 등)에 의존할 필요가 있습니다.
부작용을 일으킬 수 있는 표현을 삽입해야 합니다.
가장 심플한 솔루션:
static void die() {
while(1)
__asm("");
}
이미 Clang이 무한 루프를 방출하도록 하는 방법에 대해 설명한 다른 답변은 인라인 어셈블리 언어 또는 기타 부작용을 수반합니다.이것이 정말로 컴파일러 버그인지 확인하고 싶습니다.구체적으로는, LLVM의 오랜 버그입니다.C와 같이, 「부작용이 없는 모든 루프는 반드시 종료한다」라고 하는 C++ 개념을 적용했습니다.이 버그는 LLVM 12에서 마침내 수정되었습니다.
예를 들어 Rust 프로그래밍 언어도 무한 루프를 허용하고 LLVM을 백엔드로 사용하지만 동일한 문제가 있었습니다.
LLVM 12는mustprogress
함수가 반드시 반환되지 않는 경우를 나타내기 위해 생략할 수 있는 속성입니다.clang 12는 이를 고려하여 갱신되었습니다.이 예에서는 clang 12.0.0이 올바르게 컴파일 되어 있지만 clang 11.0.1에서는 컴파일되지 않았습니다.
이것은 쨍그랑 버그입니다.
... 무한 루프를 포함하는 함수를 인라인할 때.동작은 다음과 같습니다.while(1);
메인에 직접 나타나는데 냄새가 많이 나요.
요약 및 링크는 @Arnavion의 답변을 참조하십시오.나머지 답변은 알려진 버그는 고사하고 버그임을 확인하기 전에 작성되었습니다.
제목 질문에 답하려면:최적화되지 않는 무한 빈 루프를 만들려면 어떻게 해야 합니까?-
Clang 3.9 이후의 이 버그를 회피하기 위한 매크로를 만듭니다.(이전 버전의 Clang은 루프를 유지하거나 무한 루프가 있는 함수의 비인라인 버전으로를 내보냅니다).그것은 안전해 보인다.print;while(1);print;
기능을 호출자(Godbolt)에 연결합니다. -std=gnu11
대.-std=gnu99
아무것도 변하지 않아
GNU C에만 관심이 있다면 루프 내의 P__J__도 작동하며 이를 이해하는 컴파일러에 대한 주변 코드 최적화를 해치지 않습니다.GNU C Basic asm 문장은 암묵적으로 존재하기 때문에 이는 C 추상 머신에서와 같은 횟수만큼 "실행"해야 하는 가시적인 부작용으로 간주됩니다.(그리고 Clang은 GCC 매뉴얼에 기재된 바와 같이 C의 GNU 사투리를 구현합니다.)
일부 사람들은 빈 무한 루프를 최적화하는 것이 합법적일 수 있다고 주장해왔다.동의하지1 않습니다. 하지만 이를 받아들인다고 해도 Clang이 루프가 도달 불가능하다고 가정하고 함수의 끝에서 다음 함수로 떨어지거나 랜덤 명령으로 디코딩되는 가비지에 빠지는 것은 합법적일 수 없습니다.
(그것은 Clang++ 규격에 준거한 것입니다만, 아직 그다지 유용하지는 않습니다).부작용이 없는 무한 루프는 C++에서는 UB이지만, C에서는 UB입니다.
while(1); 정의되지 않은 동작은 C에 있습니까?UB는 컴파일러가 UB와 확실히 마주치게 되는 실행 경로 상의 코드에 대해 기본적으로 모든 것을 내보낼 수 있도록 합니다.안asm
이 UB for C++를 회피합니다.그러나 실제로 Clang 컴파일을 C++로 한다고 해서 C와 같이 인라이닝하는 경우를 제외하고 상수 표현의 무한 빈 루프가 제거되지는 않습니다.)
수동으로 인라인화하면 Clang의 컴파일 방법이 변경됩니다.asm에는 무한 루프가 존재합니다.규칙변호사 POV에게 기대하는 바입니다.
#include <stdio.h>
int main() {
printf("begin\n");
while(1);
//infloop_nonconst(1);
//infloop();
printf("unreachable\n");
}
Godbolt 컴파일러 탐색기에서는 Clang 9.0 - O3가 C로 컴파일됩니다.-xc
) x86-64의 경우:
main: # @main
push rax # re-align the stack by 16
mov edi, offset .Lstr # non-PIE executable can use 32-bit absolute addresses
call puts
.LBB3_1: # =>This Inner Loop Header: Depth=1
jmp .LBB3_1 # infinite loop
.section .rodata
...
.Lstr:
.asciz "begin"
같은 컴파일러로 같은 옵션을 사용하여 컴파일러가main
라고 부르는 것infloop() { while(1); }
먼저 똑같이puts
단, 명령어 전송을 정지합니다.main
그 이후로는요앞에서 설명한 바와 같이 실행은 함수의 끝에서 다음 함수로 넘어갑니다(단, 스택이 함수 엔트리에 대해 잘못 정렬되어 유효한 테일콜도 아닙니다).
유효한 옵션은 다음과 같습니다.
- 을 방출하다.
label: jmp label
무한 루프 - 또는 (무한 루프를 삭제할 수 있는 경우)는 다른 콜을 발신하여두 번째 스트링을 출력하고 나서
return 0
부터main
.
「도달할 수 없다」라고 인쇄하지 않고 크래시 하거나 계속하는 것은, 확실히 C11 의 실장에 있어서 바람직하지 않습니다.다만, UB 가 없는 경우는 제외됩니다.
각주 1:
참고로, C11이 빈 상태(I/O, 휘발성, 동기화 또는 기타 가시적인 부작용 없음)에서도 연속 표현 무한 루프에 대한 종료를 가정할 수 없다는 증거의 표준을 인용한 @Lundin의 답변에 동의합니다.
이것은 루프를 일반 CPU의 빈 asm 루프로 컴파일할 수 있는 조건입니다.(본문이 소스에 비어 있지 않은 경우에도 루프가 실행되고 있는 동안 데이터 레이스 UB가 없으면 변수에 대한 할당을 다른 스레드 또는 신호 핸들러에 표시할 수 없습니다.따라서 실장에 준거하면 필요에 따라 이러한 루프바디를 삭제할 수 있습니다.그러면 루프 자체를 제거할 수 있는지에 대한 의문이 남습니다.ISO C11은 명시적으로 「아니오」라고 합니다).
C11은 이 경우를 구현이 종료될 것으로 상정할 수 없는 경우(UB가 아닌 경우)로 간주하고 있기 때문에 실행 시 루프가 존재하도록 의도하고 있는 것은 분명합니다.한정된 시간에 무한한 양의 작업을 수행할 수 없는 실행 모델을 사용하여 CPU를 대상으로 하는 구현은 비어 있는 일정한 무한 루프를 제거할 이유가 없습니다.또는 일반적으로도, 정확한 표현은 "종료할 것으로 가정할 수 있는지" 여부에 대한 것입니다.루프가 종료할 수 없는 경우는 수학이나 무한에 대해 어떤 주장을 하든 가상 머신에서 무한히 많은 양의 작업을 수행하는 데 시간이 걸리더라도 이후 코드는 도달할 수 없다는 것을 의미합니다.
게다가 Clang은 ISO C 준거 DeathStation 9000 뿐만이 아니라, 커널이나 임베디드 기기등의 실제의 저레벨 시스템 프로그래밍에 도움이 되는 것을 목적으로 하고 있습니다.따라서 C11에 대한 인수를 받아들일지 여부에 따라 C11의 삭제가 허용됩니다.while(1);
클랭이 실제로 그렇게 하고 싶어한다는 것은 말이 안 된다.쓰시면while(1);
아마 사고가 아니었을 거예요(실행시 변수 제어식을 사용하여) 실수로 무한대로 끝나는 루프를 제거하는 것은 도움이 될 수 있으며, 컴파일러가 이를 수행하는 것이 타당합니다.
다음 인터럽트까지 회전하고 싶은 경우는 드물지만, C로 쓰면 그렇게 됩니다.(또한 무한 루프가 래퍼 함수 안에 있을 때 Clang을 제외하고 GCC와 Clang에서는 어떤 일이 일어나는지)
예를 들어 기본 OS 커널에서는 스케줄러가 실행할 태스크가 없는 경우 유휴 태스크를 실행할 수 있습니다.그 첫 번째 구현은 다음과 같습니다.while(1);
.
또는 전력 절약 아이돌 기능이 없는 하드웨어의 경우, 이것이 유일한 구현일 수 있습니다.(2000년대 초반까지만 해도 x86에서는 드물지 않았다고 생각합니다.단,hlt
CPU가 저전력 아이돌 상태가 될 때까지, IDK 로 상당한 전력 절약이 이루어졌을 경우)라는 지시가 존재합니다.
참고로, 클랭은 또 다른 악동작을 합니다goto
:
static void die() {
nasty:
goto nasty;
}
int main() {
int x; printf("begin\n");
die();
printf("unreachable\n");
}
질문에서와 같은 출력이 생성됩니다.
main: # @main
push rax
mov edi, offset .Lstr
call puts
.Lstr:
.asciz "begin"
C11에서는 다음과 같은 내용만 기재되어 있는 것을 알 수 없습니다.
6.8.6.1 (2) A
goto
statement를 지정하면 엔클로징 함수의 이름 있는 라벨이 앞에 붙는 문으로 무조건 점프합니다.
~하듯이goto
는, 「중요한 스테이트먼트」가 아닙니다(6.8.5 리스트).while
,do
그리고.for
) 특별한 "종료-유예" 면죄부에는 어떠한 내용도 적용되지 않습니다.
원래 질문의 Godbolt 링크 컴파일러는 x86-64 Clang 9.0.0이며 플래그는 다음과 같습니다.-g -o output.s -mllvm --x86-asm-syntax=intel -S --gcc-toolchain=/opt/compiler-explorer/gcc-9.2.0 -fcolor-diagnostics -fno-crash-diagnostics -O2 -std=c11 example.c
x86-64 GCC 9.2와 같은 다른 제품에서는 다음과 같은 완벽한 기능을 얻을 수 있습니다.
.LC0:
.string "begin"
main:
sub rsp, 8
mov edi, OFFSET FLAT:.LC0
call puts
.L2:
jmp .L2
플래그:-g -o output.s -masm=intel -S -fdiagnostics-color=always -O2 -std=c11 example.c
나는 악마의 옹호자 역할을 하고 표준이 컴파일러가 무한 루프를 최적화하는 것을 명시적으로 금지하지는 않는다고 주장할 것이다.
제어식이 상수식이 아닌 반복문은 입력/출력 연산을 실행하지 않고 휘발성 객체에 액세스하지 않으며 본문에서 동기화 또는 원자 연산을 실행하지 않으며 식을 제어하거나 (for 스테이트먼트의 경우) 그 식-3을 실행한다고 가정할 수 있다.inate.displaces)
해석해 봅시다.특정 기준을 충족하는 반복문은 종료되는 것으로 간주할 수 있습니다.
if (satisfiesCriteriaForTerminatingEh(a_loop))
if (whatever_reason_or_just_because_you_feel_like_it)
assumeTerminates(a_loop);
이는 기준이 충족되지 않을 경우 어떤 일이 일어나는지에 대한 어떠한 설명도 하지 않으며, 표준의 다른 규칙이 준수되는 한 루프가 종료될 수 있다고 가정해도 명시적으로 금지되지 않습니다.
do { } while(0)
또는while(0){}
컴파일러가 단순히 종료한다고 가정할 수 있는 조건을 충족하지 못하는 모든 반복문(문장)입니다.
하지만 컴파일러는 그냥 최적화만 할 수 있을까요?while(1){}
아웃?
추상기계에서 모든 표현은 의미론에 의해 지정된 대로 평가된다.실제 구현에서는 그 값이 사용되지 않고 필요한 부작용이 발생하지 않는다고 추론할 수 있는 경우(함수를 호출하거나 휘발성 객체에 액세스하여 발생하는 부작용 포함)에는 표현의 일부를 평가할 필요가 없습니다.
이는 진술이 아닌 표현을 언급하기 때문에 100% 설득력이 있는 것은 아니지만 다음과 같은 통화는 확실히 허용됩니다.
void loop(void){ loop(); }
int main()
{
loop();
}
건너뜁니다.흥미롭게도, 클랭은 그것을 건너뛰고, gcc는 건너뛰지 않는다.
이것은 Clang 컴파일러의 버그인 것 같습니다.만약 어떤 강제성이 없다면die()
정적 기능으로서 기능하는 것을 없애다static
만들어 내다inline
:
#include <stdio.h>
inline void die(void) {
while(1)
;
}
int main(void) {
printf("begin\n");
die();
printf("unreachable\n");
}
Clang 컴파일러로 컴파일하면 예상대로 동작하며 휴대성도 뛰어납니다.
컴파일러 탐색기(godbolt.org) - clang 9.0.0-O3 -std=c11 -pedantic-errors
main: # @main
push rax
mov edi, offset .Lstr
call puts
.LBB0_1: # =>This Inner Loop Header: Depth=1
jmp .LBB0_1
.Lstr:
.asciz "begin"
나는 이것이 단지 오래된 벌레일 뿐이라고 확신해 왔다.아래에 나의 테스트, 특히 이전에 가졌던 몇 가지 추론을 위해 표준 위원회에서의 논의에 대한 언급을 남겨두겠습니다.
이것은 정의되지 않은 동작이라고 생각합니다(끝 참조).Clang에는 구현이1개밖에 없습니다.GCC는 실제로 예상대로 동작하며, 이 기능을 최적화되어 있습니다.unreachable
문을 인쇄하지만 루프는 남습니다.Clang이 인라인을 조합하여 루프를 사용하여 무엇을 할 수 있는지 판단할 때 이상한 결정을 내리는 방법도 있습니다.
이 동작은 특히 이상합니다.최종 인쇄를 삭제하기 때문에 무한 루프를 "표시"할 수 있지만, 루프도 마찬가지입니다.
내가 보기엔 더 안 좋아인라인 삭제:
die: # @die
.LBB0_1: # =>This Inner Loop Header: Depth=1
jmp .LBB0_1
main: # @main
push rax
mov edi, offset .Lstr
call puts
.Lstr:
.asciz "begin"
그 때문에, 함수가 작성되어 콜이 최적화됩니다.이는 예상보다 훨씬 더 탄력적입니다.
#include <stdio.h>
void die(int x) {
while(x);
}
int main() {
printf("begin\n");
die(1);
printf("unreachable\n");
}
함수에 대해 최적의 어셈블리가 아니지만 함수 호출이 다시 최적화되었습니다.더 나쁜 것은:
void die(x) {
while(x++);
}
int main() {
printf("begin\n");
die(1);
printf("unreachable\n");
}
로컬 변수 추가 및 증가, 포인터 전달, 로컬 변수 사용으로 다른 테스트를 많이 만들었습니다.goto
이쯤 되면 난 포기하겠어쨍그랑을 사용해야 하는 경우
static void die() {
int volatile x = 1;
while(x);
}
그 일을 해냅니다.최적화에 실패하여(분명히), 용장 최종적으로는 남습니다.printf
적어도 프로그램은 정지하지 않는다.결국 GCC인가?
부록
David와 논의한 결과, 표준에는 "조건이 일정하면 루프가 종료된다고 가정하지 않을 수 있다"는 문구가 없는 것으로 나타났습니다.따라서 표준에서는 관찰할 수 있는 동작은 없습니다(표준에 정의되어 있는 바와 같이).나는 일관성을 주장할 것입니다.컴파일러가 루프가 종료된다고 가정하여 루프를 최적화하고 있다면 다음 문장을 최적화해서는 안 됩니다.
Heck n1528은 이러한 동작을 정의되지 않은 동작이라고 합니다.구체적으로는
이를 위한 주요 문제는 코드가 잠재적으로 비종단 루프를 통과할 수 있다는 것입니다.
여기서부터는 무엇이 허용되느냐가 아니라 우리가 원하는 것(예상되는 것)에 대한 논의로만 나누어질 수 있다고 생각한다.
다음과 같은 것이 도움이 되는 것 같습니다.
#include <stdio.h>
__attribute__ ((optnone))
static void die(void) {
while (1) ;
}
int main(void) {
printf("begin\n");
die();
printf("unreachable\n");
}
Clang에게 하나의 함수가 예상대로 무한 루프를 발생시키는 것을 최적화하지 않도록 명시적으로 지시합니다.이렇게 모든 최적화를 끄는 대신 특정 최적화를 선택적으로 비활성화할 수 있는 방법이 있으면 좋겠습니다.클랭은 여전히 두 번째 코드 발신을 거부한다.printf
,그래도.그렇게 하기 위해, 나는 안에 있는 코드를 더 수정해야만 했다.main
대상:
volatile int x = 0;
if (x == 0)
die();
무한 루프 함수에 대한 최적화를 해제하고 무한 루프를 조건부로 호출해야 할 것 같습니다.실제 세계에서는 후자가 거의 항상 해당된다.
준거 실장은 프로그램의 실행 시간이나 실행 명령의 수에 대해 임의의 제한을 가할 수 있으며, 이러한 제한이 위반되거나 "만약(as-if)" 규칙에 따라 불가피하게 위반된다고 판단될 경우 임의의 방법으로 동작할 수 있습니다.N1570 5.2.4.1에 기재되어 있는 모든 제한을 번역 제한에 도달하지 않고 명목상 실행하는 프로그램을 적어도1개 이상 정상적으로 처리할 수 있는 경우, 제한의 존재 여부, 문서화 범위 및 그 초과 효과는 모두 구현의 품질에 관한 관할구역 외의 문제입니다.(표준의)
이 표준의 의도는 컴파일러가 다음과 같이 가정해서는 안 된다는 것이 매우 명확하다고 생각합니다.while(1) {}
부작용도 없이 루프하다break
스테이트먼트가 종료됩니다.일부 사람들이 생각하는 것과 달리, 이 기준서의 작성자들은 편집자의 어리석거나 둔감하도록 권유하지 않았다.적합한 구현은 중단되지 않는다면 우주에 있는 원자보다 더 많은 부작용 없는 명령을 실행하는 프로그램을 종료하기로 결정하는 데 유용할 수 있지만 품질 구현은 종료에 대한 어떠한 가정에 기초하지 않고 오히려 그렇게 하는 것이 우리가 될 수 있다는 근거에 기초해서 그러한 행동을 수행해야 한다.(클랭의 행동과 달리) 쓸모없는 것보다 더 나쁘지는 않을 것이다.
루프는 부작용이 없기 때문에 최적화할 수 있습니다.루프는 사실상 0단위의 작업 반복 횟수입니다.이것은 수학이나 논리학에서는 정의되어 있지 않습니다.또한 표준에서는 각 것이 제로 타임에 완료될 수 있는 경우 구현이 무한히 많은 것을 완료할 수 있는지 여부를 나타내고 있지 않습니다.Clang의 해석은 무한 곱하기 0을 무한이 아닌 0으로 취급하는 데 있어 완벽하게 타당하다.이 표준에서는 루프 내의 모든 작업이 실제로 완료되었을 경우 무한 루프가 종료될 수 있는지 여부를 설명하지 않습니다.
컴파일러는 표준에서 정의된 대로 관찰할 수 없는 동작을 최적화할 수 있습니다.여기에는 실행 시간도 포함됩니다.루프가 최적화되지 않은 경우 무한대의 시간이 걸린다는 사실을 유지할 필요는 없습니다.이를 훨씬 짧은 실행 시간으로 변경할 수 있습니다.실제로 대부분의 최적화 포인트로 변경할 수 있습니다.루프가 최적화되었습니다.
clang이 코드를 순진하게 변환하더라도 각 반복을 이전 반복 시간의 절반으로 완료할 수 있는 최적화 CPU를 상상할 수 있습니다.그것은 말 그대로 무한 루프를 한정된 시간 안에 완성할 것이다.이러한 최적화 CPU는 표준을 위반합니까?CPU의 최적화를 너무 잘하면 기준에 어긋난다고 하는 것은 매우 어불성설인 것 같습니다.컴파일러도 마찬가지입니다.
만약 그렇지 않다면 죄송합니다.저는 우연히 이 게시물을 발견했습니다.Gentoo Linux distro를 오랫동안 사용해 왔기 때문에 컴파일러가 코드를 최적화하지 않으려면 -O0(제로)를 사용해야 한다는 것을 알고 있습니다.궁금해서 위의 코드를 컴파일하여 실행했는데 루프가 무한히 진행됩니다.clang-9을 사용하여 컴파일:
cc -O0 -std=c11 test.c -o test
비어 있다while
루프는 시스템에 부작용을 일으키지 않습니다.
그래서 쨍그랑 소리를 내며 제거한다.의도된 행동을 성취하기 위한 "더 나은" 방법들이 있는데, 이것은 여러분이 여러분의 의도를 더 분명하게 하도록 강요합니다.
while(1);
바아드입니다.
언급URL : https://stackoverflow.com/questions/59925618/how-do-i-make-an-infinite-empty-loop-that-wont-be-optimized-away
'programing' 카테고리의 다른 글
getter에서 Vue 체인 여러 필터 (0) | 2022.08.11 |
---|---|
VueJ: 렌더링을 또는 (0) | 2022.08.11 |
vue 앱 새로 고침: GET /path를 가져올 수 없음 (0) | 2022.08.10 |
여러 v-for 루프...다른 방법은 없을까? (0) | 2022.08.10 |
'vue'에서 'createApp' 내보내기를 찾을 수 없습니다. (0) | 2022.08.10 |