C23 표준, DOOM을 망가뜨리다? C 언어의 숨겨진 함정!

by DD
3개월 전
조회수 6

Fedora Linux의 패키지 빌드 과정에서 Chocolate Doom이 C23 표준과의 충돌로 인해 실패함

C23 표준 도입으로 인해 기존의 커스텀 boolean 타입과 `false` 키워드 간의 충돌 발생

`_Bool` 타입 사용 시, 예상과 다른 메모리 초기화 및 비교 연산으로 인해 게임 엔진이 오작동함

Undefined Behavior(UB)로 인해 발생한 문제임을 확인하고, 컴파일러의 동작 방식을 분석함

C23 표준 도입과 컴파일 오류

Fedora Linux의 대규모 패키지 재빌드 과정에서 Chocolate Doom 패키지가 빌드 오류를 겪었다. 이는 GCC 15.0.1 버전에서 C23 표준을 기본으로 사용하면서 발생한 문제로, 기존 코드에서 자체적으로 정의한 `boolean` 타입과 C23의 `bool`, `true`, `false` 키워드 간의 충돌이 원인이었다. 컴파일러 옵션(-std=gnu23) 변경으로 인해, 기존 코드의 boolean 정의가 더 이상 유효하지 않게 된 것이다.

문제 해결 과정: 코드 수정 및 C99 표준 채택

문제 해결을 위해 저자는 세 가지 해결책을 고려했다. 첫 번째는 C 표준을 C17으로 명시적으로 설정하는 것이었지만, 근본적인 해결책이 아니라고 판단했다. 두 번째는 `#ifdef`를 사용하여 C23 모드에서 내장 `bool` 타입을 사용하도록 코드를 수정하는 것이었다. 마지막으로, `enum`의 값을 `False`와 `True`로 변경하는 방법도 고려했다. 결국, 저자는 두 번째 방법을 선택하여 문제를 해결하고, 이후 C99 표준을 채택하는 방향으로 결정되었다.

_Bool 타입 사용 시의 예상치 못한 동작

C99 표준을 채택하고 `_Bool` 타입을 사용하면서, 예상치 못한 문제가 발생했다. `_Bool` 타입으로 선언된 변수에 -1로 초기화된 후, 해당 값을 비교하는 과정에서 오류가 발생한 것이다. 디버깅 결과, `_Bool` 타입은 1바이트 크기로, -1로 초기화된 경우 예상과 다른 비교 연산 결과를 보였다. 이는 C 언어의 Undefined Behavior(UB)로 인해 발생한 문제로, `_Bool` 타입에 유효하지 않은 값을 할당했기 때문이다.

어셈블리 코드 분석을 통한 문제의 근본 원인 파악

문제를 더욱 깊이 파악하기 위해, 저자는 어셈블리 코드를 분석했다. `boolean`이 `enum` 타입일 때는 예상대로 `== false` 조건이 0과 비교되고, `== true` 조건이 1과 비교되었다. 그러나 `_Bool` 타입일 때는 `== false` 조건이 `!= 1`로, `== true` 조건이 `!= 0`으로 변환되어, 255와 같은 값을 가질 경우 예상치 못한 결과를 초래했다. 이러한 동작은 C99 표준의 6.2.6절(Representation of types)에 명시된 UB에 해당한다.

UB(Undefined Behavior)와 컴파일러의 역할

결론적으로, 이 문제는 C 언어의 UB(Undefined Behavior) 영역에 속하며, 컴파일러는 이러한 상황에서 예상치 못한 동작을 보일 수 있다. 저자는 UBSan을 사용하여 문제를 확인하고, C99 표준을 참조하여 근거를 찾았다. 컴파일러는 UB 상황에서 최적화를 수행할 수 있으며, 이는 예상치 못한 결과를 초래할 수 있다. 따라서, C 언어 프로그래밍 시 UB를 피하고, 코드의 안전성을 확보하는 것이 중요하다.

The little bool of doom

댓글 0

첫 번째 댓글을 남겨보세요!