오염
모든 불안전한 코드가 최소 예외 안전성을 가지도록 보장해야 하지만, 모든 타입들이 최대 예외 안전성을 보장하는 것은 아닙니다. 어떤 타입이 최대 예외 안전성을 보장하더라도, 여러분의 코드가 그 타입에 추가적인 의미를 부여할 수 있습니다.
예를 들어, 정수는 확실히 예외에 안전하지만, 그 자체로는 의미가 없습니다. panic!
하는 코드가 그 정수를 올바르게 갱신하지 못할 수도 있고, 그러면 프로그램의 상태가 모순된 상태가 됩니다.
이런 것은 보통 괜찮은데요, 예외를 마주하는 모든 것은 곧 소멸되기 때문입니다. 예를 들어, 만약 여러분이 어떤 Vec
을 다른 스레드로 보내고 그 스레드가 panic!
한다면, 그 Vec
이 이상한 상태로 있어도 상관 없습니다.
어차피 해제되고 영원히 없어질 거니까요. 하지만 어떤 타입들은 패닉 경계를 통과해서 값들을 들여오는 것에 능합니다.
이런 타입들은 panic!
을 마주할 경우 자신을 오염시키도록 명시적으로 선택할 수 있습니다. 오염은 특별히 무언가를 요구하지는 않습니다. 보통 이것이 의미하는 것은 그냥 더 이상의 정상적인 사용을 방지하는 것입니다.
이것의 가장 주목할 만한 예는 표준 라이브러리의 Mutex
타입입니다. Mutex
는 그 MutexGuard
들 (락을 얻었을 때 Mutex
가 반환하는 것) 중 하나가 panic!
중에 해제될 때, 그 자신을 오염시킵니다.
이 이후의 Mutex
를 잠그려는 어떤 시도도 Err
를 반환하거나 panic!
할 겁니다.
Mutex
가 오염되는 것은 러스트가 보통 신경쓰는 정도의 안정성을 위해서가 아닙니다. 그것은 잠겨 있는 도중 panic!
을 마주한 Mutex
에서 나온 데이터를 멋모르고 사용하는 것에 대한 안전 장치입니다.
이런 Mutex
에 있는 데이터는 아마도 수정되던 도중이었을 것이며, 따라서 모순되거나 불완전한 상태에 있을 수 있기 때문입니다. 코드가 잘 쓰여졌다면 이런 타입을 사용하는 것이 메모리 안전성을 침해할 수 없다는 것이 중요합니다.
결국 최소한은 예외에 안전해야 하니까요!
하지만 Mutex
가, 이를테면, 제대로 배열되지 않은 BinaryHeap
을 포함하고 있다면, 이것을 사용하는 어떤 코드도 코드의 작성자가 의도한 것을 하지는 못할 겁니다. 그렇기 때문에 프로그램은 정상적으로 진행되어서는 안됩니다.
그래도, 만약 그 값을 가지고 무언가를 할 수 있다고 여러분이 확신한다면, Mutex
는 어쨌든 락을 얻을 수 있도록 하는 메서드를 제공합니다. 안전하기 때문이죠. 다만 말이 안 될 수도 있을 뿐이죠.