Unsafe Operation in Rust Programming

Rust ProgrammingServer Side ProgrammingProgramming

Unsafe Operations are done when we want to ignore the norm that Rust provides us. There are different unsafe operations that we can use, mainly:

  • dereferencing raw pointers
  • accessing or modifying static mutable variables
  • calling functions or methods which are unsafe

Though it is not recommended by Rust that we should use unsafe operations at all, we should use them only when we want to bypass the protections that are put in by the compiler.

Raw Pointers

 In Rust, the raw pointers * and the references &T perform almost the same thing, but references are always safe, as they are guaranteed by the compiler to point to valid data due to the borrow checker.

It should also be noted that dereferencing a raw pointer can only be done through an unsafe block.

Example

Consider the example shown below:

fn main() {
   let raw_p: *const u32 = &10;
   println!("{}",*raw_p == 10);
}

The above code will result in an error. 

Output

error[E0133]: dereference of raw pointer is unsafe and requires
unsafe function or block
 --> src/main.rs:4:19
  |
7 | println!("{}",*raw_p == 10);
  | ^^^^^^ dereference of raw pointer
  |
  = note: raw pointers may be NULL, dangling or unaligned; they
can violate aliasing rules and cause data races: all of these are
undefined behavior

In order to avoid this error, we need to use an unsafe block and then, we can do the dereferencing of a raw pointer.

Example

Consider the code shown below: 

Live Demo

fn main() {
   let raw_p: *const u32 = &10;
   unsafe {
      assert!(*raw_p == 10);
   }
   println!("worked fine!")
}

Output

worked fine!

Unsafe function

Calling an unsafe function in Rust will result in an error.

Example

Consider the code shown below:

use std::slice;

fn main() {
   let some_vector = vec![1, 2, 3];

   let pointer = some_vector.as_ptr();
   let length = some_vector.len();
   let my_slice: &[u32] = slice::from_raw_parts(pointer, length);
   assert_eq!(some_vector.as_slice(), my_slice);
}

Output

In the above code, we have a slice::from_raw_parts function that is unsafe, and if we try to run this code, we will see an error like this -

error[E0133]: call to unsafe function is unsafe and requires
unsafe function or block
--> src/main.rs:10:28
   |
10 | let my_slice: &[u32] = slice::from_raw_parts(pointer,
length);
   |
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
   |
   = note: consult the function's documentation for information on
how to avoid undefined behavior

Instead of calling the function from just anywhere, we should call the unsafe function from inside an unsafe block. 

Example

Consider the code shown below:

Live Demo

use std::slice;

fn main() {
   let some_vector = vec![1, 2, 3, 4];

   let pointer = some_vector.as_ptr();
   let length = some_vector.len();

   unsafe {
      let my_slice: &[u32] = slice::from_raw_parts(pointer, length);
      assert_eq!(some_vector.as_slice(), my_slice);
   }
   println!("worked fine!!")
}

Output

worked fine!!
raja
Published on 05-Apr-2021 07:46:47
Advertisements