C++26, while(true); 무한 루프를 더 이상 미정의 동작으로 두지 않는다
- C++26은 P2809R3로 조건 없는
while(true);같은 사소한 무한 루프를 미정의 동작에서 제외함. 이 제안은 결함 보고서로도 채택돼서 이전 C++ 모드에도 적용될 수 있음. - C++11의 전진 보장(forward progress guarantee) 규칙상 종료, I/O 호출, volatile 접근, 동기화 중 아무것도 하지 않는 무한 루프는 UB였고, Clang은 루프를 지워 실행이 다음 함수로 흘러들어가 "Hello world!"를 출력했음.
- C11은 제어식이 상수 표현식인 루프를 종료한다고 가정하지 못하게 했지만 C++은 이 규칙을 받아들이지 않아, while(1);이 C에서는 정의되고 C++에서는 UB인 상태가 15년 가까이 이어졌음.
- P2809R3는 C의 넓은 규칙 대신 본문이 완전히 비어 있고 제어식이 true인 상수 표현식인 경우만 사소한 무한 루프로 정의하고, 조건을 만족하면 루프 본문을
std::this_thread::yield()호출로 교체함. - 임베디드와 커널에서 치명적 오류 시 멈추는 halt-on-error 패턴으로 실제로 쓰이는데, 루프가 제거되면 장치가 손상된 상태로 계속 실행돼 보안 취약점이 된다는 점이 실질적 영향임.
Hacker News opinions
블로그 breadcrumb의 "blog", "year" 링크가 404 뜨더라. 다른 글은 볼 수 있으니 별로 상관은 없음.
unreachable()가 실제로 실행된다는 건 상상도 못 했다. 실무에서 볼 일은 거의 없겠지만 #ifdef 겹치면 괴상한 일이 생기긴 하지.
그게 바로 UB의 본질임. 컴파일러가 네 기대대로 동작할 의무가 없음.
실무에서 제일 흔한 발등 찍기임. 반환형이 있는데 return이 없는 함수는 그냥 끝을 넘어 계속 실행됨. -Wreturn-type 켜면 막을 수 있음.
100년의 1/6 동안이나 C++ 표준이 가장 단순한 무한 루프를 망가뜨리고 이제야 고친 거임. 사람이 진짜 프로그램 짠다는 걸 모르냐.
컴파일러 회사들은 벤치마크로 승부하니까 이런 미친 최적화를 넣는 거임.
부작용 없는 무한 루프는 실용적인 프로그램이 아님. CPU 사이클과 전력 낭비일 뿐이고, 컴파일 실패시키는 게 맞음.
아님. 임베디드 halt-on-error처럼 꼭 필요한 경우도 있음. OS가 없어서 그냥 멈추는 패턴 말이지.
러스트는 무한 루프를 아예 키워드로 만들 만큼 중요하게 보고, 인터럽트 기반 슈퍼루프도 흔함.
함수가 다른 함수로 흘러들어간다는 게 이해가 안 됨. 이런 동작이 왜 있는 거임?
CPU는 함수가 아니라 명령어만 봄. 반환이 빠진 어긋난 함수를 만들면 다음 메모리의 함수 코드로 그냥 이어짐.
어셈블리를 보면 main이 UB라서 컴파일러가 정의를 포기한 거임. 함수 레이블은 왜 남기는지 모르겠는데, 그냥 트랩 명령 하나 넣으면 안 되나.
널 종료 문자열은 billion dollar mistake라면서 왜 UB는 아닌 거임?
널 종료 문자열은 피할 수 있지만 UB는 성능 때문에 어느 정도 필요함. C와 C++가 너무 많은 걸 UB로 몰아넣은 게 문제지.
y*x/y를 x로 바꾸고 싶으면 y가 0이 아니라는 걸 증명하든가 UB에 기대야 함.
무한 루프를 미정의 동작으로 두는 건 아쉬움. 경고라도 띄워주면 좋았을 텐데.
진짜 충격은 yield() 호출을 넣는다는 것임. 라이브러리 호출 하나 없는 무한 루프에 시스템 콜을 끼워 넣다니. 무한 루프는 그냥 무한 루프로 컴파일돼야 함.