매우 간단한 코드의“잘못된 하드웨어 명령”


9

모호한 주장을 조사 하면서이 작은 테스트 프로그램을 작성했습니다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

왓.

최적화없이 컴파일하면 예상대로 중단됩니다. 나는 어셈블리를 보았고 모든 종소리와 휘파람없이 main기능은 다음과 같습니다.

_main:                                  ## @main
    pushq   %rbp
    movq    %rsp, %rbp
    ud2

ud2명확하게 정의되지 않은 동작에 대한 지침은 어디에 있습니까 ? 앞서 언급 한 모호한 주장 인 "반환하지 않는 함수는 UB이다"는 강조가된다. 그래도 여전히 믿기가 어렵습니다. 정말!? 스핀 루프를 안전하게 작성할 수 없습니까?

그래서 내 질문은 다음과 같습니다.

  1. 이것은 무슨 일이 일어나고 있는지에 대한 정확한 독서입니까?
  2. 그렇다면 누군가가 그것을 확인하는 공식 리소스를 알려줄 수 있습니까?
  3. 이 유형의 최적화가 발생하기를 원하는 상황은 무엇입니까?

관련 정보

$ 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

3
IIRC, signed int overflow는 UB입니다.
wildplasser

1
int n = 0unsigned int n = 0;while (1);
^^^^

1
흠 ... 컴파일러 탐색기 clang은 -O gcc.godbolt.org/z/NTCQYT 및 자체 번역없이 자체 대상 점프 명령을 받습니다 . 여러 버전에서 일관된 것으로 보입니다. 그러나 나는 또한 C 표준에 따르면 부작용이 없으면 비 종료가 ub라고 말합니다 (참조하지는 않지만) . Hans Boehm은 이것이 불가능한 특정 컴파일러 최적화를 허용한다고 설명합니다. open-std.org/jtc1/sc22/wg14/www/docs/n1528.htm
Gene

1
정의되지 않은 동작은 무한 루프가 아닌 부호있는 정수 오버플로입니다. 당신은을 사용하여 문제를 해결할 수unsigned int
MM

2
@ 제네 나는 그렇게 생각하지 않습니다. 비 충돌 제어식이있는 부작용이없는 루프는 종료 된 것으로 간주 될 수 있지만 ( port70.net/~nsz/c/c11/n1570.html#6.8.5p6 ) 사용 중 루프는 양호합니다. UB는 정수 오버플로에 있지만 UD 명령으로 예제를 재현 할 수는 없습니다.
PSkocik

답변:


3

현재 문제가되는 코드에 대해 ud2를 얻는다면 컴파일러는 적합한 C 컴파일러가 아닙니다. 컴파일러 버그를보고 할 수 있습니다.

C ++에서이 코드는 실제로 UB입니다. 스레드가 추가되면 (각각 C11 및 C ++ 11), 멀티 스레드되지 않은 프로그램의 기본 실행 스레드를 포함하여 모든 스레드에 대해 순방향 진행 보장이 이루어졌습니다.

C ++에서 모든 스레드는 예외없이 진행되어야합니다. 그러나 C에서는 제어 표현식이 상수 표현식 인 루프가 진행될 필요가 없습니다. 내 이해는 C 가이 예외를 추가했다는 것입니다. 왜냐하면 임베디드 코딩 while(1) {}에서 스레드를 걸기 위해 이미 사용하는 것이 일반적이기 때문 입니다.

더 자세한 답변과 비슷한 질문


예, 나는 ud2C 코드에서 얻었지만 C ++ 앞으로 진행 보증 (연구 할 수있는 용어라고 함)에 대한 정보를 포함시켜 주셔서 감사합니다. 질문을 준비하고있었습니다.
luqui

내가 표준위원회가 말하려고 한 것에 대한 더 좋은 표현은 특정 작업을지나 루프 내의 모든 것을 지연시키는 것이 프로그램 동작에 눈에 띄게 영향을 미치지 않는다면 루프의 실행을 전체적으로 연기하는 것은 그 과거의 작업으로 간주되지 않는다는 것입니다 관찰 가능한 행동 변화.
supercat
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.