undefined behavior는 아무 이유없이 그렇게 된게 아니라 잘못된 프로그램의 의미를 어떻게든 정의해야하기 때문에 필요한거임.

UB를 안쓰려면 두가지 방법이 있음.

1. UB 대신 defined behavior를 씀. 적당한게 없으면 error를 냄. (error를 낸다는건 프로그램이 즉시 오류 메시지를 출력하면서 뻗는거임. UB랑은 다름)

2. type system을 강하게 만들어서 잘못된 프로그램을 컴파일 타임에 거부하면 의미를 정의하지 않아도 됨


일단 1번의 문제는 퍼포먼스 하락임.

예를 들어 integer overflow를 UB대신 error로 정의하면 정수연산마다 overflow 검사를 해야하고, modular arithmetic으로 정의하는 경우에도 induction variable widening 같은 최적화가 안됨.

data race도 대표적인 UB인데 data race를 error로 정의하긴 곤란하고, defined behavior를 줄려면 atomic operation을 써야할건데 그러면 성능이 많이 깎임. (atomic 연산 쓰면 컴파일러 최적화가 잘 안됨)


2번 해결책은 상당한 PL 백그라운드가 필요함. C/C++ 만들어지던 시기엔 무리였던것 같고, 러스트가 최신 PL 이론을 많이 반영해서 사용자 한테 노출되는 UB를 많이 줄였지.

근데 이것도 별로 완벽한 해결책은 아님. decidable한 type checking 알고리즘을 포기하지 않는한 타입시스템에는 한계가 있음. (Rice's theorem)

러스트가 unsafe로 타입시스템에 백도어를 뚫은것도 이런 이유고.

일단 unsafe가 생기면 unsafe 프로그램도 의미를 정의 해야하니 여기선 결국 UB를 써서 해야됨.



결론 : 러스트 써라