ef049c9667663e6d110f1667b7890c502f5048d52629d9663860616342764419
언세이프 러스트는 러스트의 일부분이며 언세이프를 사용하더라도 변수의 소유권과 수명검사는 여전히 작동하는 등 메모리 안전 기능이 완전히 꺼진게 아니며 언세이프로 인한 문제 발생 시 좁은 범위의 unsafe 블록만 디버깅 하면 됩니다.
unsafe 러스트
지금까지 살펴본 모든 코드에는 컴파일 타임에 러스트의 메모리 안전 보장이 적용되었습니다. 그러나 러스트에는 이러한 메모리 안전 보장을 적용하지 않는 두 번째 언어가 숨겨져 있습니다: 이 언어는 안전하지 않은 러스트 (unsafe Rust) 라고 불리며 일반 러스트와 똑같이 작동하지만 추가 슈퍼파워를 제공합니다.
정적 분석은 본질적으로 보수적이기 때문에 안전하지 않은 러스트가 존재합니다. 컴파일러가 코드가 보증을 준수하는지 여부를 판단하려고 할 때, 일부 유효하지 않은 프로그램을 허용하는 것보다 일부 유효한 프로그램을 거부하는 것이 더 낫습니다. 코드가 아마도 괜찮을 수 있겠지만, 러스트 컴파일러는 확신할 수 있는 정보가 충분하지 않다면 코드를 거부할 것입니다. 이러한 경우, 안전하지 않은 코드를 사용하여 컴파일러에게 ‘날 믿어, 내가 뭘 하고 있는지 알고 있어’라고 말할 수 있습니다. 하지만, 안전하지 않은 러스트를 사용하는 것은 사용자의 책임하에 사용해야 한다는 점에 유의하시기를 바랍니다: 안전하지 않은 코드를 잘못 사용하면, 메모리 불안정성으로 인하여 널 포인터 역참조와 같은 문제가 발생할 수 있습니다.
안전하지 않은 러스트로 전환하려면 unsafe 키워드를 사용한 다음 새 블록을 시작하여 안전하지 않은 코드를 집어넣으세요. 안전하지 않은 러스트에서는 안전하지 않은 슈퍼파워라고 부르는 다섯 가지 작업을 수행할 수 있습니다. 이러한 슈퍼파워에는 다음과 같은 기능이 포함됩니다:
- 원시 포인터 (raw pointer) 역참조하기
- 안전하지 않은 함수 혹은 메서드 호출하기
- 가변 정적 변수에 접근하기 및 수정하기
- 안전하지 않은 트레이트 구현하기
- union의 필드 접근하기
unsafe가 대여 검사기를 끄거나 러스트의 다른 안전성 검사를 비활성화하지 않는다는 점을 이해하는 것이 중요합니다: 안전하지 않은 코드에서 참조를 사용하면, 검사는 여전히 이루어집니다. unsafe 키워드는 컴파일러가 메모리 안전성을 검사하지 않는 위의 다섯 가지 기능 허용만 제공할 뿐입니다. 안전하지 않은 블록 내부에서도 여전히 어느 정도의 안전성을 확보할 수 있습니다.
함수에 안전하지 않은 코드가 포함되어 있다고 해서 전체 함수를 안전하지 않은 것으로 표시할 필요는 없습니다. 사실 안전하지 않은 코드를 안전한 함수로 감싸는 것은 일반적인 추상화입니다. 예를 들어, 안전하지 않은 코드가 약간 필요한 표준 라이브러리의 split_at_mut 함수를 살펴봅시다. 이를 어떻게 구현할 수 있는지 살펴보겠습니다. 이 안전한 메서드는 가변 슬라이스에 대해 정의됩니다: 하나의 슬라이스를 받아 인수로 주어진 인덱스에서 슬라이스를 분할하여 두 개로 만듭니다. 예제 19-4는 split_at_mut을 사용하는 방법을 보여줍니다.
let mut v = vec![1, 2, 3, 4, 5, 6];
let r = &mut v[..];
let (a, b) = r.split_at_mut(3);
assert_eq!(a, &mut [1, 2, 3]);
assert_eq!(b, &mut [4, 5, 6]);
안전한 러스트만 사용하여 이 함수를 구현할 수는 없습니다. 예제 19-5처럼 시도해 볼 수 있지만 컴파일되지 않을 것입니다. 간단하게 하기 위해 split_at_mut를 메서드가 아닌 함수로 구현하고 제네릭 타입 T 대신 i32 값의 슬라이스에 대해서 만으로 구현하겠습니다.
fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
let len = values.len();
assert!(mid <= len);
(&mut values[..mid], &mut values[mid..])
}
$ cargo run
Compiling unsafe-example v0.1.0 (file:///projects/unsafe-example)
error[E0499]: cannot borrow `*values` as mutable more than once at a time
--> src/main.rs:6:31
|
1 | fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
| - let's call the lifetime of this reference `'1`
...
6 | (&mut values[..mid], &mut values[mid..])
| --------------------------^^^^^^--------
| | | |
| | | second mutable borrow occurs here
| | first mutable borrow occurs here
| returning this value requires that `*values` is borrowed for `'1`
For more information about this error, try `rustc --explain E0499`.
error: could not compile `unsafe-example` due to previous error
러스트의 대여 검사기는 슬라이스의 서로 다른 부분을 빌린다는 것을 이해할 수 없습니다; 러스트는 그저 동일한 슬라이스를 두 번 빌린다는 것만 알고 있습니다. 슬라이스의 서로 다른 부분을 빌리는 것은 두 슬라이스가 겹치지 않기 때문에 기본적으로 괜찮지만, 러스트는 이를 알아차릴 만큼 똑똑하지 못합니다.
다음은 split_at_mut의 구현체를 작동시키기 위해 unsafe 블록, 원시 포인터, 그리고 안전하지 않은 함수 호출을 사용하는 방법을 보여줍니다.
use std::slice; fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) { let len = values.len(); let ptr = values.as_mut_ptr(); assert!(mid <= len); unsafe { ( slice::from_raw_parts_mut(ptr, mid), slice::from_raw_parts_mut(ptr.add(mid), len - mid), ) } }결과인 split_at_mut 함수를 unsafe로 표시할 필요는 없으며,안전한 러스트에서 이 함수를 호출할 수 있다는 점에 유의하세요. 이 함수는 접근할 수 있는 데이터에서 유효한 포인터만 생성하기 때문에, unsafe 코드를 안전한 방식으로 사용하는 함수의 구현을 통해 안전하지 않은 코드에 대한 안전한 추상화를 만든 것이 되었습니다.반면 예제 19-7의 slice::from_raw_parts_mut 사용은 슬라이스가 사용될 때 크래시가 발생하기 쉽습니다. 이 코드는 임의의 메모리 위치를 가져와서 10,000개의 아이템을 가진 슬라이스를 생성합니다.
use std::slice; let address = 0x01234usize; let r = address as *mut i32; let values: &[i32] = unsafe { slice::from_raw_parts_mut(r, 10000) };예제 19-7: 임의의 메모리 위치로부터 슬라이스 생성하기
이 임의 위치에 있는 메모리를 소유하지 않고, 이 코드가 생성하는 슬라이스가 유효한 i32 값들을 포함하고 있는지에 대한 보장이 없습니다. values를 마치 유효한 슬라이스인 것처럼 사용하려고 하면 정의되지 않은 동작이 발생합니다.
unsafe을 사용하여 방금 설명한 다섯 가지 동작 (슈퍼파워) 중 하나를 수행하는 것은 잘못된 것도 아니고, 심지어 눈살을 찌푸릴 일도 아닙니다. 하지만 컴파일러가 메모리 안전성을 유지할 수 없기 때문에, unsafe 코드를 올바르게 만드는 것은 더 까다롭습니다. unsafe 코드를 사용해야 할 이유가 있다면 그렇게 할 수 있으며, 명시적인 unsafe 어노테이션을 통해 문제가 발생했을 때 문제의 원인을 더 쉽게 추적할 수 있습니다.
지적 수준이 미달이신 분들이 이해할 수 있을만한 내용도 아니고 설득 될거라 생각하지도 않지만 저도 복습 겸 해서 정리해봤습니다. ㅎㅎ
혹시라도 러스트를 배울만한 지적 수준이 높으신 분이 있다면 도움이 될 지도 모르죠.
꽃개위에 qr코드 뭐노 저거 스캔하면 해킹당함?
사칭범이 나대길래 디지털 서명을 qr코드로 박았습니다. 짤 밑에 hex코드가 공개키입니다.
아 참고로 서명한 메시지는 글 제목입니다. 이걸로는 같은 제목으로 조작할 수 있어서 본문까지 서명에 포함되도록 수정 예정입니다.
이 댓글은 게시물 작성자가 삭제하였습니다.
이 댓글은 게시물 작성자가 삭제하였습니다.
주제를 벗어나는 딴 얘기 하셔서 삭제처리하겠습니다.
이 댓글은 게시물 작성자가 삭제하였습니다.
이 댓글은 게시물 작성자가 삭제하였습니다.
AI딸깍 복사 읽지도앉고 ㅋㅋ 러스트가 ㅄ인 이유로 그대로 ai 딸깍해도 논문 한편 나온다
아닌데요. 공식문서 중에서 나름 지적 수준이 충분치 못한 분들이 읽기 쉽도록 추려서 가져왔는데요. 근데 보니까 확실히 지적 수준이 낮으면 건들리기 어렵겠더라고요. 나름 추려서 가져온다고 했는데도 러스트 설계가 너무 정교해서 핵심을 담기 위해 글이 많이 길어진거 같습니다.
@글쓴 프갤러(221.149) AI딸깍 텍스트 마크다운 티나는데 애휴
@ㅇㅇ(211.206) https://doc.rust-kr.org/ch19-01-unsafe-rust.html 긴말 안하겠습니다. 계속 우기시면 본인 지적 수준만 드러나는거죠 뭐
@글쓴 프갤러(221.149) ai가 출처도 가져오긴하지 ㅋㅋ
본문이 뭐가 문제냐면 unsafe 위에 safe를 구축해놓고 러스트는 안전하다는 개뻥을 전세계 상대로 치니까 문제인거여. unsafe위에 safe 구축은 c/c++을 파이선으로 래핑하는거랑 뭐가 달라 ㅎㅎ