Technical notes

Share this post
Rust - unsafe
moshan.substack.com

Rust - unsafe

Mo Shan
Apr 24
Share this post
Rust - unsafe
moshan.substack.com
  • We can use the unsafe functions like this

use std::collections::HashMap; 

fn main() {
    let map = HashMap::new(); 
    let mut map = explain("empty", map); 
    
    map.insert(String::from("a"), 1); 
    explain("added 1", map); 
}

fn explain<K, V>(name: &str, map: HashMap<K, V>) -> HashMap<K, V> {
    let arr: [usize; 6] = unsafe { std::mem::transmute(map) }; 
    println!("{}: bucket mask 0x{:x}, ctrl 0x{:x}, growth_left: {}, items: {}", 
        name, arr[2], arr[3], arr[4], arr[5]); 
        
    unsafe{ std::mem::transmute(arr) }
}

Sometimes rust will provide both safe and unsafe version, eg from_utf8, and from_utf8_unchecked, the unchecked version will be much faster, but it does not provide safety check

  • Unsafe can also be used for naked pointers

fn main() {
    let mut age = 18; 
    
    let r1 = &age as *const i32; 
    let r2 = &mut age as *mut i32; 
    
    unsafe {
        println!("r1: {}, r2: {}", *r1, *r2); 
    }
}

fn immutable_mutable_cant_coexist() {
    let mut age = 18; 
    let r1 = &age; 
    // this is wrong 
    // let r2 = &mut age; 
}
  • unsafe can be used for FFI

use std::mem::transmute; 

fn main() {
    let data = unsafe {
        let p = libc::malloc(4); 
        let arr: &mut [u8; 4] = transmute(p); 
        arr
    }; 
    
    data.copy_from_slice(&[1, 2, 3, 4]); 
    println!("data: {:?}", data); 
    
    unsafe { libc::free(transmute(data)) }; 
}
  • unsafe should not be used for static mut, and in macro

  • when using unsafe function, should comment in code why it is safe here

fn main() {
    let mut s = "harry-potter".to_string(); 
    let r = s.as_mut(); 
    
    if let Some((s1, s2)) = split(r, '-') {
        println!("s1: {}, s2: {}", s1, s2); 
    }
}

fn split(s: &str, sep: char) -> Option<(&str, &str)> {
    let pos = s.find(sep); 
    
    pos.map(|pos| {
        let len = s.len(); 
        let sep_len = sep.len_utf8(); 
        
        // safety: pos is from find, so it is at the boundary
        // the code below is thus safe to use 
        unsafe { (s.get_unchecked(0..pos), s.get_unchecked(pos + sep_len..len)) }
    })
}

Share this post
Rust - unsafe
moshan.substack.com
Comments

Create your profile

0 subscriptions will be displayed on your profile (edit)

Skip for now

Only paid subscribers can comment on this post

Already a paid subscriber? Sign in

Check your email

For your security, we need to re-authenticate you.

Click the link we sent to , or click here to sign in.

TopNew

No posts

Ready for more?

© 2022 Mo Shan
Privacy ∙ Terms ∙ Collection notice
Publish on Substack Get the app
Substack is the home for great writing