오염

모든 불안전한 코드가 최소 예외 안전성을 가지도록 보장해야 하지만, 모든 타입들이 최대 예외 안전성을 보장하는 것은 아닙니다. 어떤 타입이 최대 예외 안전성을 보장하더라도, 여러분의 코드가 그 타입에 추가적인 의미를 부여할 수 있습니다. 예를 들어, 정수는 확실히 예외에 안전하지만, 그 자체로는 의미가 없습니다. panic!하는 코드가 그 정수를 올바르게 갱신하지 못할 수도 있고, 그러면 프로그램의 상태가 모순된 상태가 됩니다.

이런 것은 보통 괜찮은데요, 예외를 마주하는 모든 것은 곧 소멸되기 때문입니다. 예를 들어, 만약 여러분이 어떤 Vec을 다른 스레드로 보내고 그 스레드가 panic!한다면, 그 Vec이 이상한 상태로 있어도 상관 없습니다. 어차피 해제되고 영원히 없어질 거니까요. 하지만 어떤 타입들은 패닉 경계를 통과해서 값들을 들여오는 것에 능합니다.

이런 타입들은 panic!을 마주할 경우 자신을 오염시키도록 명시적으로 선택할 수 있습니다. 오염은 특별히 무언가를 요구하지는 않습니다. 보통 이것이 의미하는 것은 그냥 더 이상의 정상적인 사용을 방지하는 것입니다. 이것의 가장 주목할 만한 예는 표준 라이브러리의 Mutex 타입입니다. Mutex는 그 MutexGuard들 (락을 얻었을 때 Mutex가 반환하는 것) 중 하나가 panic! 중에 해제될 때, 그 자신을 오염시킵니다. 이 이후의 Mutex를 잠그려는 어떤 시도도 Err를 반환하거나 panic!할 겁니다.

Mutex가 오염되는 것은 러스트가 보통 신경쓰는 정도의 안정성을 위해서가 아닙니다. 그것은 잠겨 있는 도중 panic!을 마주한 Mutex에서 나온 데이터를 멋모르고 사용하는 것에 대한 안전 장치입니다. 이런 Mutex에 있는 데이터는 아마도 수정되던 도중이었을 것이며, 따라서 모순되거나 불완전한 상태에 있을 수 있기 때문입니다. 코드가 잘 쓰여졌다면 이런 타입을 사용하는 것이 메모리 안전성을 침해할 수 없다는 것이 중요합니다. 결국 최소한은 예외에 안전해야 하니까요!

하지만 Mutex가, 이를테면, 제대로 배열되지 않은 BinaryHeap을 포함하고 있다면, 이것을 사용하는 어떤 코드도 코드의 작성자가 의도한 것을 하지는 못할 겁니다. 그렇기 때문에 프로그램은 정상적으로 진행되어서는 안됩니다. 그래도, 만약 그 값을 가지고 무언가를 할 수 있다고 여러분이 확신한다면, Mutex는 어쨌든 락을 얻을 수 있도록 하는 메서드를 제공합니다. 안전하기 때문이죠. 다만 말이 안 될 수도 있을 뿐이죠.