Help with Freeing Raw Pointers

Trying to learn raw pointers in Rust, wanted to free the allocated ones but it is giving me Segfaults & Invalid pointers error. And why does dealloc need its first arg as *mut u8 and why not *mut T

#[derive(Debug)]
struct Person(&'static str);

fn main() {
    // 1. Creating Raw Pointers
    let p1: *mut u8 = &mut 32; // Raw pointer On Stack
    let p2: *mut Person = Box::into_raw(Box::new(Person("A"))); // Raw pointer On Heap

    // 2. Using Raw Pointers to access data
    let v1: u8 = unsafe {*p1};
    let v2: Person = unsafe {*Box::from_raw(p2)};
    println!("{} {:?}", v1, v2);
    use std::ptr::drop_in_place;
    use std::alloc::{dealloc, Layout};
    unsafe {
        // 3. run destructors
        drop_in_place(p1);
        drop_in_place(p2);
        
        // 4. free up memory allocated
        dealloc(p1 as *mut u8, Layout::new::<u8>()); 
            // free(): invalid pointer
            // Aborted (core dumped)
        dealloc(p2 as *mut u8, Layout::new::<Person>());
            // Segmentation fault (core dumped)
    }
}

Box::from_raw turns the raw pointer back into a Box, which frees its memory automatically when it goes out of scope. So if you call Box::from_raw, you should not free the memory manually.

If you want to manage the memory manually, you can use std::ptr::read instead of Box::from_raw to extract the value from the raw pointer.

1 Like

Thanks got it. I tried the below code and its working.

let p2: *mut Person = Box::into_raw(Box::new(Person("A")));
let v2: Person = unsafe {std::ptr::read(p2 as *const Person)};
unsafe {
        drop_in_place(p2);
        dealloc(p2 as *mut u8, Layout::new::<Person>());
}

May I know why it is throwing error for below code?

use std::ptr::drop_in_place;
use std::alloc::Layout;
use std::alloc::dealloc;
fn main() {
    let p1: *mut u8 = &mut 32;
    unsafe {
            drop_in_place(p1);
            dealloc(p1 as *mut u8, Layout::new::<u8>()); 
    }
}

Because the p1, which is came from the stack, is not allocated via the global allocator.

https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html#tymethod.dealloc

2 Likes

Also note that you are dropping the same value twice here: Once when v2 goes out of scope, and once when you call drop_in_place(p2). After you have used ptr::read to extract the value from a pointer, you should not call drop_in_place on the pointer.

(In your example, Person doesn't have any destructors, so dropping it has no effect. But if you changed the Person type to contain a type with a destructor like String, this would be undefined behavior.)

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.