[Rust] 안전하지 않은 러스트
Updated:
개요
- 메모리 안전성 보장을 강제하지 않는 숨겨진 내부의 두번째 언어
- 빌림 검사기 혹은 다른 어떤 러스트의 안전성 검사 기능을 끄는 것은 아님
- 코드가 필연적으로 위험하다던가 절대적으로 메모리 안전성 문제를 가지고 있음을 의미하는 것이 아님
- 코드가 올바른 방법으로 메모리에 접근할 것임을 확실히 해두는 것
- 존재 이유
- 정적 분석이 선천적으로 보수적이기 때문
- 하드웨어가 선천적으로 안전하지 않기 때문
- 저수준의 시스템 프로그래밍 작업은 이 언어의 목표 중 하나
- 단점
- 개발자가 위험성을 고스란히 받아들여야 함
- unsafe 키워드
- 안전하지 않은 러스트로 전환해주는 키워드
- unsafe 뒤에 안전하지 않은 코드를 감싸주는 새 블록을 생성
- 메모리 안전성과 관련된 어떠한 에러라도 unsafe 블록 내에 있을 것임
- unsafe 블록을 최대한 작게 유지
- 외국 함수 인터페이스(Foreign Function Interface, FFI)
- 다른 언어로 작성된 함수를 호출
- extern 키워드를 이용
- 다른 언어에서 러스트 함수 호출
- extern 키워드를 이용
- #[no_mangle] 어노테이션을 추가 필요
- 맹글링(mangling)
- 컴파일 과정에서 함수의 이름을 변경
- 맹글링(mangling)
안전하지 않은 슈퍼파워(unsafe superpowers)
- 안전하지 않은 러스트 내에서 할 수 있는 4개의 행동
- 로우 포인터(raw pointer)를 역참조
- 불변
*const T
- 가변
*mut T
- 성질
- 빌림 규칙 무시가 허용되어 불변 및 가변 포인터 양쪽 모두를 갖거나 같은 위치에 여러 개의 가변 포인터를 갖을 수 있음
- 유효한 메모리를 가리키고 있음을 보장하지 않음
- 널이 될 수 있음
- 자동 메모리 정리가 구현되어 있지 않음
- 불변
- 안전하지 않은 함수 혹은 메소드 호출
- unsafe 블록 내에서 호출해야함
- 문서를 읽었고 적절한 사용법을 이해했음을 러스트에게 단언
- 가변 정적 변수(mutable static variable)의 접근 혹은 수정
- 안전하지 않은 트레잇 구현
- 로우 포인터(raw pointer)를 역참조
예제 - 로우 포인터(raw pointer)를 역참조
- 코드
-
fn main() { let mut i = 1; let i1 = &i as *const i32; let i2 = &mut i as *mut i32; unsafe { println!("1 : {}, {}", *i1, *i2); *i2 = 2; println!("2 : {}, {}", *i1, *i2); } }
-
- 실행 결과
-
1 : 1, 1 2 : 2, 2
-
예제 - 안전하지 않은 함수 혹은 메소드 호출
- 코드
-
unsafe fn func() { let i = 1; let i1 = &i as *const i32; println!("{}", *i1); } fn main() { unsafe { func(); } }
-
- 실행 결과
-
1
-
예제 - 외국 함수 인터페이스(Foreign Function Interface, FFI)
- 코드
-
extern "C" { fn abs(x: i32) -> i32; } fn main() { unsafe { println!("{}, {}", abs(-1), abs(1)); } }
-
- 실행 결과
-
1, 1
-
예제 - 가변 정적 변수(mutable static variable)의 접근 혹은 수정
- 코드
-
static TEST_1: i32 = 1; static mut TEST_2: &str = "a"; fn main() { println!("1 : {}", TEST_1); unsafe { println!("2 : {}", TEST_2); } unsafe { TEST_2 = "b"; } unsafe { println!("3 : {}", TEST_2); } }
-
- 실행 결과
-
1 : 1 2 : a 3 : b
-
예제 - 안전하지 않은 트레잇 구현
- 코드
-
unsafe trait Test {} unsafe impl Test for i32 {} fn main() {}
-